Fix bug 2232: change deployment option helm-chart-v2 to helm-chart so that NBI accepts it
[osm/NG-UI.git] / src / app / packages / ns-packages / ns-composer / NSComposerComponent.ts
1 /*
2  Copyright 2020 TATA ELXSI
3
4  Licensed under the Apache License, Version 2.0 (the 'License');
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8   http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15
16  Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
17 */
18 /**
19  * @file NS Compose Component
20  */
21 import { isNullOrUndefined } from 'util';
22 import { HttpHeaders } from '@angular/common/http';
23 import { Component, ElementRef, Injector, ViewChild, ViewEncapsulation } from '@angular/core';
24 import { ActivatedRoute, Router } from '@angular/router';
25 import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
26 import { TranslateService } from '@ngx-translate/core';
27 import { NotifierService } from 'angular-notifier';
28 import { APIURLHEADER, CONSTANTNUMBER, ERRORDATA, MODALCLOSERESPONSEDATA, MODALCLOSERESPONSEWITHCP } from 'CommonModel';
29 import { ConfirmationTopologyComponent } from 'ConfirmationTopology';
30 import * as d3 from 'd3';
31 import { DataService } from 'DataService';
32 import { environment } from 'environment';
33 import * as HttpStatus from 'http-status-codes';
34 import * as jsyaml from 'js-yaml';
35 import {
36   CCI,
37   COMPOSERNODES,
38   DF,
39   GRAPHDETAILS,
40   NSData,
41   NSDATACREATION,
42   NSDDetails,
43   Tick, TickPath, VLC, VLD, VNFPROFILE
44 } from 'NSDModel';
45 import { RestService } from 'RestService';
46 import { SharedService } from 'SharedService';
47 import { VNFD, VNFData } from 'VNFDModel';
48
49 /**
50  * Creating component
51  * @Component takes NSComposerComponent.html as template url
52  */
53 @Component({
54   selector: 'app-ns-composer',
55   templateUrl: './NSComposerComponent.html',
56   styleUrls: ['./NSComposerComponent.scss'],
57   encapsulation: ViewEncapsulation.None
58 })
59 /** Exporting a class @exports NSComposerComponent */
60 export class NSComposerComponent {
61   /** To inject services @public */
62   public injector: Injector;
63   /** View child contains graphContainer ref @public  */
64   @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
65   /** dataService to pass the data from one component to another @public */
66   public dataService: DataService;
67   /** Contains VNFD Informations @public */
68   public nsPackageDetails: NSData = { id: '', name: '', description: '', version: '', designer: '' };
69   /** Contains VL Details @public */
70   public virtualLinkDesc: VLD = {
71     id: '',
72     'mgmt-network': true
73   };
74   /** Contains the information of the type of modification @public  */
75   public putType: string;
76   /** Contains index of old VLD @public  */
77   public getOldVLDIndex: string[];
78   /** Conatins mousedown action @public */
79   public mousedownNode: COMPOSERNODES = null;
80   /** Conatins mouseup action @public */
81   public mouseupNode: COMPOSERNODES = null;
82   /** Conatins mousedownLink action @public */
83   public mousedownLink: COMPOSERNODES = null;
84   /** Conatins current Selection node action @public */
85   public currentSelectedNode: COMPOSERNODES = null;
86   /** Conatins current Selection node action @public */
87   public currentSelectedLink: COMPOSERNODES = null;
88   /** Need to show the NSD Details @public */
89   public isShowNSDDetails: boolean = true;
90   /** Contains the node information of VL @public */
91   public vlNodes: {}[] = [];
92   /** Need to show the VL Details @public */
93   public isShowVLDetails: boolean = false;
94   /** Contains the node information of VNF @public */
95   public vnfNodes: {}[] = [];
96   /** contains the VNF Details @public */
97   public vnfData: VNFPROFILE;
98   /** contains the Virtual Link connectivity Details @public */
99   public virtualLinkProfileID: string;
100   /** Need to show the VNF Details @public */
101   public isShowVNFDetails: boolean = false;
102   /** Contains the node information of CP @public */
103   public cpNodes: {}[] = [];
104   /** Need to show the CP Details */
105   public cpData: CCI;
106   /** Need to show the VNF Details @public */
107   public isShowCPDetails: boolean = false;
108   /** random number count @public */
109   public randomNumberLength: number;
110   /** Contains the vnfd information @public */
111   public vnfList: VNFD[] = [];
112   /** Add the activeclass for the selected @public */
113   public activeClass: string = 'active';
114   /** Add the fixed class for the freeze @public */
115   public fixedClass: string = 'fixed';
116   /** Check the loading results @public */
117   public isLoadingResults: boolean = true;
118   /** Give the message for the loading @public */
119   public message: string = 'PLEASEWAIT';
120   /** Get VNF selected node @public */
121   public getVNFSelectedData: VNFD;
122   /** Assign the forcesimulation active @public */
123   public forceSimulationActive: boolean = false;
124   /** Assign pinned class for the button when freezed @public */
125   public classApplied: boolean = false;
126   /** Contains sidebar open status @public */
127   public sideBarOpened: boolean = false;
128   /** Contains SVG attributes @private */
129   // eslint-disable-next-line @typescript-eslint/no-explicit-any
130   private svg: any;
131   /** Contains the Drag line */
132   // eslint-disable-next-line @typescript-eslint/no-explicit-any
133   private dragLine: any;
134   /** Contains VL node @private */
135   // eslint-disable-next-line @typescript-eslint/no-explicit-any
136   private vlNode: any;
137   /** Contains VNFD node @private */
138   // eslint-disable-next-line @typescript-eslint/no-explicit-any
139   private vnfdnode: any;
140   /** Contains CP node @private */
141   // eslint-disable-next-line @typescript-eslint/no-explicit-any
142   private cpnode: any;
143   /** Rendered nodes represent VL @private */
144   // eslint-disable-next-line @typescript-eslint/no-explicit-any
145   private gvlNode: any;
146   /** Rendered nodes represent VL @private */
147   // eslint-disable-next-line @typescript-eslint/no-explicit-any
148   private gvnfdNode: any;
149   /** Rendered nodes represent VL @private */
150   // eslint-disable-next-line @typescript-eslint/no-explicit-any
151   private gcpNode: any;
152   /** Contains forced node animations @private */
153   // eslint-disable-next-line @typescript-eslint/no-explicit-any
154   private force: any;
155   /** Contains all the selected node @private */
156   private selectedNode: COMPOSERNODES[] = [];
157   /** Contains the connected point @private */
158   private connectionPoint: string;
159   /** Contains id of the node @private */
160   private identifier: string;
161   /** Contains copy of NSD information @private */
162   private nsdCopy: string;
163   /** Contains the VNFD copy @private */
164   private vnfdCopy: string;
165   /** Contains path information of the node */
166   // eslint-disable-next-line @typescript-eslint/no-explicit-any
167   private path: any;
168   /** Contains the node information @private */
169   private nodes: COMPOSERNODES[] = [];
170   /** Contains the link information of nodes @private */
171   private links: {}[] = [];
172   /** Contains the NS information @private */
173   private nsData: NSDDetails;
174   /** Instance of the rest service @private */
175   private restService: RestService;
176   /** Service holds the router information @private */
177   private router: Router;
178   /** Holds teh instance of AuthService class of type AuthService @private */
179   private activatedRoute: ActivatedRoute;
180   /** Notifier service to popup notification @private */
181   private notifierService: NotifierService;
182   /** Controls the header form @private */
183   private headers: HttpHeaders;
184   /** Contains tranlsate instance @private */
185   private translateService: TranslateService;
186   /** Contains lastkeypressed instance @private */
187   private lastKeyDown: number = -1;
188   /** Instance of the modal service @private */
189   private modalService: NgbModal;
190   /** Setting the Value of connection point refrence of the CP @private */
191   private setVnfdConnectionPointRef: string;
192   /** Setting the Value of VL name for confirmation @private */
193   private vlName: string;
194   /** Setting the Value of VNFD name for confirmation @private */
195   private setVnfdName: string;
196   /** Contains all methods related to shared @private */
197   private sharedService: SharedService;
198   /** Contains selected node VNF profile objects @private */
199   private selectedVNFProfile: VNFPROFILE[];
200
201   constructor(injector: Injector) {
202     this.injector = injector;
203     this.restService = this.injector.get(RestService);
204     this.dataService = this.injector.get(DataService);
205     this.router = this.injector.get(Router);
206     this.activatedRoute = this.injector.get(ActivatedRoute);
207     this.notifierService = this.injector.get(NotifierService);
208     this.translateService = this.injector.get(TranslateService);
209     this.modalService = this.injector.get(NgbModal);
210     this.sharedService = this.injector.get(SharedService);
211   }
212   /** Lifecyle Hooks the trigger before component is instantiated @public */
213   public ngOnInit(): void {
214     this.identifier = this.activatedRoute.snapshot.paramMap.get('id');
215     this.generateData();
216     this.headers = new HttpHeaders({
217       'Content-Type': 'application/gzip',
218       Accept: 'application/json',
219       'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
220     });
221   }
222   /** Events handles at drag on D3 region @public */
223   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
224   public drag(ev: any): void {
225     if (ev.target.id === 'vl') {
226       ev.dataTransfer.setData('text', ev.target.id);
227     } else {
228       ev.dataTransfer.setData('text', ev.target.attributes['data-id'].value);
229     }
230   }
231   /** On clicking redirect to NS edit page @public */
232   public onEdit(): void {
233     this.router.navigate(['/packages/ns/edit/', this.identifier]).catch((): void => {
234       // Catch Navigation Error
235     });
236   }
237   /** Events handles drop at D3 region @public */
238   public drop(ev: DragEvent): void {
239     ev.preventDefault();
240     const getDropedName: string = ev.dataTransfer.getData('text');
241     if (getDropedName === 'vl') {
242       this.svg.selectAll('*').remove();
243       this.vldropComposer();
244     } else {
245       this.svg.selectAll('*').remove();
246       const vnfdName: string = ev.dataTransfer.getData('text');
247       this.vnfdropComposer(vnfdName);
248     }
249   }
250   /** Drop VL Composer Data @public */
251   public vldropComposer(): void {
252     this.randomNumberLength = CONSTANTNUMBER.randomNumber;
253     const generateId: string = 'ns_vl_' + this.sharedService.randomString();
254     if (this.nsData['virtual-link-desc'] === undefined) {
255       this.nsData['virtual-link-desc'] = [];
256     }
257     this.nsData['virtual-link-desc'].push({
258       id: generateId,
259       'mgmt-network': false
260     });
261     this.putType = 'nsdadd';
262     this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
263   }
264   /** Drop VNFD Composer Data @public */
265   public vnfdropComposer(vnfdName: string): void {
266     const vnfID: string = 'ns_vnfd_' + this.sharedService.randomString();
267     if (this.nsData.df.length > 0) {
268       this.addVNFDID(vnfdName);
269       this.nsData.df.forEach((res: DF): void => {
270         if (res['vnf-profile'] === undefined) {
271           res['vnf-profile'] = [];
272         }
273         res['vnf-profile'].push({
274           id: vnfID,
275           'virtual-link-connectivity': [],
276           'vnfd-id': vnfdName
277         });
278       });
279     } else {
280       Object.assign(this.nsData.df, {
281         id: 'default-df',
282         'vnf-profile': [{
283           id: vnfID,
284           'virtual-link-connectivity': [],
285           'vnfd-id': vnfdName
286         }]
287       });
288     }
289     this.putType = 'vnfdadd';
290     this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
291   }
292   /** Add the VNFD-ID while drop VNFD if not exists @public */
293   public addVNFDID(vnfdName: string): void {
294     const vnfdIDArray: string[] = this.nsData['vnfd-id'];
295     if (vnfdIDArray !== undefined) {
296       if (vnfdIDArray.indexOf(vnfdName) === -1) {
297         vnfdIDArray.push(vnfdName);
298       }
299     } else {
300       Object.assign(this.nsData, {
301         'vnfd-id': [vnfdName]
302       });
303     }
304   }
305   /** Events handles allow drop on D3 region @public */
306   public allowDrop(ev: DragEvent): void {
307     ev.preventDefault();
308   }
309   /** Save NSD Information @public */
310   public saveNSD(): void {
311     if (this.nsPackageDetails.id !== undefined) {
312       this.nsData.id = this.nsPackageDetails.id;
313     }
314     if (this.nsPackageDetails.name !== undefined) {
315       this.nsData.name = this.nsPackageDetails.name;
316     }
317     if (this.nsPackageDetails.description !== undefined) {
318       this.nsData.description = this.nsPackageDetails.description;
319     }
320     if (this.nsPackageDetails.version !== undefined) {
321       this.nsData.version = this.nsPackageDetails.version;
322     }
323     if (this.nsPackageDetails.designer !== undefined) {
324       this.nsData.designer = this.nsPackageDetails.designer;
325     }
326     this.putType = 'nsdUpdate';
327     this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
328   }
329   /** Save Virtual Link @public */
330   public saveVL(vlid: string): void {
331     this.nsData['virtual-link-desc'].forEach((result: VLD): void => {
332       if (result.id === vlid) {
333         result['mgmt-network'] = !isNullOrUndefined(this.virtualLinkDesc['mgmt-network']) ? this.virtualLinkDesc['mgmt-network'] : true;
334       }
335     });
336     this.putType = 'vlUpdate';
337     this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
338   }
339   /** Add the new Data @public */
340   public addData(apiURL: string, identifier: string, data: NSDDetails, putType: string): void {
341     this.isLoadingResults = true;
342     let successMessage: string = '';
343     if (putType === 'nsdadd') {
344       successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.ADDNSD';
345     } else if (putType === 'vnfdadd') {
346       successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.ADDVNFD';
347     } else if (putType === 'cpAdded') {
348       successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.ADDNS';
349     } else if (putType === 'nsdUpdate') {
350       successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.UPDATEDSUCCESSFULLY';
351     } else if (putType === 'vlUpdate') {
352       successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.UPDATEDSUCCESSFULLY';
353     } else if (putType === 'nsddelete') {
354       successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETENSD';
355     } else if (putType === 'vnfddelete') {
356       successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETEVNFD';
357     } else if (putType === 'nsdelete') {
358       successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETENS';
359     } else if (putType === 'linkdelete') {
360       successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETELINK';
361     }
362     /** Below hide for conflicts with light weight UI */
363     const apiURLHeader: APIURLHEADER = {
364       url: apiURL + '/' + identifier + '/nsd_content',
365       httpOptions: { headers: this.headers }
366     };
367     const nsData: NSDATACREATION = { nsd: { nsd: [] } };
368     nsData.nsd.nsd = [];
369     nsData.nsd.nsd.push(data);
370     const descriptorInfo: string = jsyaml.dump(nsData, { sortKeys: true });
371     this.sharedService.targzFile({ packageType: 'nsd', id: this.identifier, descriptor: descriptorInfo })
372       .then((content: ArrayBuffer): void => {
373         this.restService.putResource(apiURLHeader, content).subscribe((res: {}): void => {
374           this.generateData();
375           this.notifierService.notify('success', this.translateService.instant(successMessage));
376           this.isLoadingResults = false;
377         }, (error: ERRORDATA): void => {
378           this.generateData();
379           this.restService.handleError(error, 'put');
380           this.isLoadingResults = false;
381         });
382       }).catch((): void => {
383         this.notifierService.notify('error', this.translateService.instant('ERROR'));
384         this.isLoadingResults = false;
385       });
386   }
387   /** Show Info @public */
388   public showInfo(): void {
389     // eslint-disable-next-line security/detect-non-literal-fs-filename
390     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
391     modalRef.componentInstance.topologyType = 'Info';
392     modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.INFO');
393     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
394       if (result) {
395         // empty
396       }
397     }).catch((): void => {
398       // Catch Navigation Error
399     });
400   }
401   /** Event to freeze the animation @public */
402   public onFreeze(): void {
403     this.classApplied = !this.classApplied;
404     const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
405     d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
406     if (alreadyFixedIsActive) {
407       this.force.stop();
408     }
409     this.forceSimulationActive = alreadyFixedIsActive;
410     this.nodes.forEach((d: COMPOSERNODES): void => {
411       d.fx = (alreadyFixedIsActive) ? null : d.x;
412       d.fy = (alreadyFixedIsActive) ? null : d.y;
413     });
414     if (alreadyFixedIsActive) {
415       this.force.restart();
416     }
417   }
418   /** Events handles when dragended @public */
419   public toggleSidebar(): void {
420     this.sideBarOpened = !this.sideBarOpened;
421     this.deselectAllNodes();
422     this.showRightSideInfo(true, false, false, false);
423   }
424   /** Prepare information for node creation of VNFD @private */
425   private generateData(): void {
426     this.generateVNFData();
427     this.generateDataNSDTopology();
428     this.sideBarOpened = false;
429   }
430   /** Prepare the information of the VNFD @private */
431   private generateVNFData(): void {
432     this.restService.getResource(environment.VNFPACKAGESCONTENT_URL).subscribe((vnfdPackageData: VNFD[]): void => {
433       this.vnfList = vnfdPackageData;
434     }, (error: ERRORDATA): void => {
435       this.restService.handleError(error, 'get');
436     });
437   }
438   /** Prepare information for node creation of NSD Topology @private */
439   private generateDataNSDTopology(): void {
440     this.nodes = [];
441     this.links = [];
442     this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL + '/' + this.identifier).subscribe((nsData: NSDDetails): void => {
443       delete nsData._admin;
444       delete nsData._id;
445       delete nsData._links;
446       this.nsData = nsData;
447       this.generateNSInfo(nsData);
448       if (nsData['virtual-link-desc'] !== undefined) {
449         /** Details of the VL */
450         this.nsDataVLD(nsData);
451       }
452       if (this.nsData.df.length > 0) {
453         this.nsData.df.forEach((res: DF): void => {
454           if (res['vnf-profile'] !== undefined) {
455             /** Details of the VNFD */
456             this.nsDataConstituentVNFD(nsData);
457           }
458         });
459       }
460       if (nsData.df.length > 0) {
461         this.nsDataVLDLinkCreation(nsData);
462       }
463       this.separateAndCreatenode();
464     }, (error: ERRORDATA): void => {
465       if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
466         this.router.navigateByUrl('404', { skipLocationChange: true }).catch((): void => {
467           // Catch Navigation Error
468         });
469       } else {
470         this.restService.handleError(error, 'get');
471       }
472       this.isLoadingResults = false;
473       this.isShowNSDDetails = false;
474     });
475   }
476   /** Generate the NS Package Information */
477   private generateNSInfo(nsData: NSDDetails): void {
478     this.nsPackageDetails.id = nsData.id;
479     this.nsPackageDetails.name = nsData.name;
480     this.nsPackageDetails.description = nsData.description;
481     this.nsPackageDetails.version = nsData.version;
482     this.nsPackageDetails.designer = nsData.designer;
483   }
484   /** nsData VL node creation function @private */
485   private nsDataVLD(nsData: NSDDetails): void {
486     nsData['virtual-link-desc'].forEach((res: VLD): void => {
487       this.nodes.push({ id: res.id, reflexive: false, type: 'vld', name: res.id, selectorId: res.id });
488     });
489   }
490   /** nsData VNFD node creation function @private */
491   private nsDataConstituentVNFD(nsData: NSDDetails): void {
492     nsData.df.forEach((resDF: DF): void => {
493       resDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
494         this.nodes.push(
495           {
496             id: resVNF['vnfd-id'] + ':' + resVNF.id,
497             reflexive: false,
498             type: 'vnfd',
499             name: resVNF['vnfd-id'],
500             nodeIndex: resVNF.id,
501             selectorId: resVNF['vnfd-id'] + '_' + resVNF.id
502           });
503         if (resVNF['virtual-link-connectivity'] !== undefined) {
504           this.nsDataCP(resVNF, resVNF.id);
505         }
506       });
507     });
508   }
509   /** nsData CP node creation function @private */
510   private nsDataCP(resVNF: VNFPROFILE, vnfID: string): void {
511     resVNF['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => {
512       resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => {
513         this.nodes.push(
514           {
515             id: vnfID + ':' + resultCCI['constituent-base-element-id'] + index + ':' + resultCCI['constituent-cpd-id'],
516             reflexive: false,
517             type: 'ns',
518             name: resultCCI['constituent-cpd-id'],
519             nodeIndex: resultCCI['constituent-base-element-id'],
520             selectorId: 'osm-' + resultCCI['constituent-cpd-id'] + '-' + vnfID + resultCCI['constituent-base-element-id'] + index
521           });
522       });
523     });
524   }
525   /** nsData Link node creation function @private */
526   private nsDataVLDLinkCreation(nsData: NSDDetails): void {
527     nsData.df.forEach((resDF: DF): void => {
528       if (resDF['vnf-profile'] !== undefined) {
529         resDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
530           this.nsdCopy = resVNF['vnfd-id'] + ':' + resVNF.id;
531           if (resVNF['virtual-link-connectivity'] !== undefined) {
532             this.nsDataVNFDConnectionPointRefrence(resVNF);
533           }
534         });
535       }
536     });
537   }
538   /** nsDataVNFDConnectionPointRefrence undefined Call this function @private */
539   private nsDataVNFDConnectionPointRefrence(resVNF: VNFPROFILE): void {
540     resVNF['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => {
541       resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => {
542         this.vnfdCopy = resultVLC['virtual-link-profile-id'];
543         this.connectionPoint = resVNF.id + ':' + resultCCI['constituent-base-element-id'] + index + ':' + resultCCI['constituent-cpd-id'];
544         const connectionPointPos: number = this.nodes.map((e: COMPOSERNODES): string => e.id).indexOf(this.connectionPoint);
545         const nsdPos: number = this.nodes.map((e: COMPOSERNODES): string => e.id).indexOf(this.nsdCopy);
546         const vnfdPos: number = this.nodes.map((e: COMPOSERNODES): string => e.id).indexOf(this.vnfdCopy);
547         this.links.push(
548           {
549             // eslint-disable-next-line security/detect-object-injection
550             source: this.nodes[connectionPointPos],
551             // eslint-disable-next-line security/detect-object-injection
552             target: this.nodes[nsdPos]
553           },
554           {
555             // eslint-disable-next-line security/detect-object-injection
556             source: this.nodes[connectionPointPos],
557             // eslint-disable-next-line security/detect-object-injection
558             target: this.nodes[vnfdPos]
559           });
560       });
561     });
562   }
563   /** Separate and create node @private */
564   private separateAndCreatenode(): void {
565     this.seprateNodes(this.nodes);
566     this.createnode(this.nodes);
567     this.isLoadingResults = false;
568   }
569   /** Get the default Configuration of containers @private */
570   private getGraphContainerAttr(): GRAPHDETAILS {
571     return {
572       width: 700,
573       height: 400,
574       nodeHeight: 50,
575       nodeWidth: 35,
576       textX: -35,
577       textY: 30,
578       radius: 5,
579       distance: 50,
580       strength: -500,
581       forcex: 2,
582       forcey: 2,
583       sourcePaddingYes: 17,
584       sourcePaddingNo: 12,
585       targetPaddingYes: 4,
586       targetPaddingNo: 3,
587       alphaTarget: 0.3,
588       imageX: -25,
589       imageY: -25,
590       shiftKeyCode: 17
591     };
592   }
593   /** Separate the nodes along with its tyep @private */
594   private seprateNodes(node: COMPOSERNODES[]): void {
595     this.vlNodes = []; this.vnfNodes = []; this.cpNodes = [];
596     node.forEach((nodeList: COMPOSERNODES): void => {
597       if (nodeList.type === 'vld') {
598         this.vlNodes.push(nodeList);
599       } else if (nodeList.type === 'vnfd') {
600         this.vnfNodes.push(nodeList);
601       } else if (nodeList.type === 'ns') {
602         this.cpNodes.push(nodeList);
603       }
604     });
605   }
606   /** Node is created and render at D3 region @private */
607   private createnode(node: COMPOSERNODES[]): void {
608     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
609     d3.selectAll('svg#graphContainer > *').remove();
610     d3.select(window).on('keydown', (): void => { this.keyDown(); });
611     d3.select(window).on('keyup', (): void => { this.keyUp(); });
612     this.svg = d3.select('#graphContainer')
613       .attr('oncontextmenu', 'return false;')
614       .attr('viewBox', `0 0 ${graphContainerAttr.width} ${graphContainerAttr.height}`)
615       .on('mousemove', (): void => { this.mousemove(); });
616     this.force = d3.forceSimulation()
617       .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
618       .force('link', d3.forceLink().id((d: TickPath): string => d.id).distance(graphContainerAttr.distance))
619       .force('center', d3.forceCenter(graphContainerAttr.width / graphContainerAttr.forcex,
620         graphContainerAttr.height / graphContainerAttr.forcey))
621       .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
622       .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
623       .on('tick', (): void => { this.tick(); });
624     this.dragLine = this.svg.append('svg:path').attr('class', 'link dragline hidden').attr('d', 'M0,0L0,0');
625     this.path = this.svg.append('svg:g').selectAll('path');
626     this.vlNode = this.svg.append('svg:g').selectAll('vlnode');
627     this.vnfdnode = this.svg.append('svg:g').selectAll('vnfdnode');
628     this.cpnode = this.svg.append('svg:g').selectAll('cpnode');
629     // app starts here
630     this.restart(node);
631   }
632   /** update force layout (called automatically each iteration) @private */
633   private tick(): void {
634     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
635     // draw directed edges with proper padding from node centers
636     this.path.attr('class', 'link').attr('d', (d: Tick): string => {
637       const deltaX: number = d.target.x - d.source.x;
638       const deltaY: number = d.target.y - d.source.y;
639       const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
640       const normX: number = deltaX / dist;
641       const normY: number = deltaY / dist;
642       const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
643       const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
644       const sourceX: number = d.source.x + (sourcePadding * normX);
645       const sourceY: number = d.source.y + (sourcePadding * normY);
646       const targetX: number = d.target.x - (targetPadding * normX);
647       const targetY: number = d.target.y - (targetPadding * normY);
648       return `M${sourceX},${sourceY}L${targetX},${targetY}`;
649     }).on('dblclick', (d: Tick): void => { this.getDeleteLinkConfirmation(d); });
650     this.vlNode.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`);
651     this.vnfdnode.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`);
652     this.cpnode.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`);
653   }
654   /** Update graph (called when needed) at D3 region @private */
655   private restart(node: COMPOSERNODES[]): void {
656     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
657     this.path = this.path.data(this.links);
658     this.vlNode = this.vlNode.data(this.vlNodes, (d: COMPOSERNODES): string => d.id);
659     this.vnfdnode = this.vnfdnode.data(this.vnfNodes, (d: COMPOSERNODES): string => d.id);
660     this.cpnode = this.cpnode.data(this.cpNodes, (d: COMPOSERNODES): string => d.id);
661     this.resetAndCreateNodes();
662     this.force.nodes(node).force('link').links(this.links);
663     this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
664   }
665   /** Rest and create nodes @private */
666   private resetAndCreateNodes(): void {
667     this.path.exit().remove();
668     this.vlNode.exit().remove();
669     this.vnfdnode.exit().remove();
670     this.cpnode.exit().remove();
671     this.getPathNodes();
672     this.getVLNodes();
673     this.getVNFDNodes();
674     this.getCPNodes();
675     this.path.merge(this.path);
676     this.vlNode = this.gvlNode.merge(this.vlNode);
677     this.vnfdnode = this.gvnfdNode.merge(this.vnfdnode);
678     this.cpnode = this.gcpNode.merge(this.cpnode);
679   }
680   /** setting the Path @private */
681   private getPathNodes(): void {
682     this.path = this.path.enter().append('svg:path');
683   }
684   /** Setting all the VL nodes @private */
685   private getVLNodes(): void {
686     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
687     this.gvlNode = this.vlNode.enter().append('svg:g');
688     this.gvlNode.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
689     this.gvlNode.append('svg:image')
690       .style('opacity', 1)
691       .attr('x', graphContainerAttr.imageX)
692       .attr('y', graphContainerAttr.imageY)
693       .call(this.onDragDrop())
694       .attr('id', (d: COMPOSERNODES): string => d.selectorId)
695       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
696       .attr('xlink:href', 'assets/images/VL.svg')
697       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
698       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
699       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.vlNode, d); this.onNodeClickToggleSidebar(); })
700       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); });
701     this.gvlNode.append('svg:text')
702       .attr('class', 'node_text')
703       .attr('y', graphContainerAttr.textY)
704       .text((d: COMPOSERNODES): string => d.id);
705   }
706   /** Setting all the VNFD nodes @private */
707   private getVNFDNodes(): void {
708     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
709     this.gvnfdNode = this.vnfdnode.enter().append('svg:g');
710     this.gvnfdNode.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
711     this.gvnfdNode.append('svg:image')
712       .style('opacity', 1)
713       .attr('x', graphContainerAttr.imageX)
714       .attr('y', graphContainerAttr.imageY)
715       .call(this.onDragDrop())
716       .attr('id', (d: COMPOSERNODES): string => d.selectorId)
717       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
718       .attr('xlink:href', 'assets/images/VNFD.svg')
719       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
720       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
721       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.vnfdnode, d); this.onNodeClickToggleSidebar(); })
722       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); });
723     this.gvnfdNode.append('svg:text')
724       .attr('class', 'node_text')
725       .attr('y', graphContainerAttr.textY)
726       .text((d: COMPOSERNODES): string => d.name);
727   }
728   /** Setting all the CP nodes @private */
729   private getCPNodes(): void {
730     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
731     this.gcpNode = this.cpnode.enter().append('svg:g');
732     this.gcpNode.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
733     this.gcpNode.append('svg:image')
734       .style('opacity', 1)
735       .attr('x', graphContainerAttr.imageX)
736       .attr('y', graphContainerAttr.imageY)
737       .call(this.onDragDrop())
738       .attr('id', (d: COMPOSERNODES): string => d.selectorId)
739       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
740       .attr('xlink:href', 'assets/images/CP.svg')
741       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
742       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
743       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.cpnode, d); this.onNodeClickToggleSidebar(); })
744       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); });
745     this.gcpNode.append('svg:text')
746       .attr('class', 'node_text')
747       .attr('y', graphContainerAttr.textY)
748       .text((d: COMPOSERNODES): string => d.name);
749   }
750   /** Events handles when mousemove it will capture the selected node data @private */
751   private mousemove(): void {
752     if (!this.mousedownNode) { return; }
753     this.dragLine.attr('d',
754       `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
755   }
756   /** Get confirmation Before Deleting the Link in Topology @private */
757   private getAddConfirmation(mouseData: COMPOSERNODES, getNsData: NSDDetails, addType: string, getVLDIndex: string): void {
758     let findVNFName: string = '';
759     let findVLDID: string = '';
760     if (mouseData.type === 'vld') {
761       findVNFName = this.mouseupNode.name;
762       findVLDID = this.mousedownNode.id;
763       this.vlName = this.mousedownNode.name;
764     } else {
765       findVNFName = this.mousedownNode.name;
766       findVLDID = this.mouseupNode.id;
767       this.vlName = this.mouseupNode.name;
768     }
769     if (getNsData['vnfd-id'] !== undefined) {
770       getNsData['vnfd-id'].forEach((resVNFid: string): void => {
771         if (resVNFid === findVNFName) {
772           this.getVNFSelectedData = this.vnfList.filter((vnfList: VNFD): boolean => vnfList.id === findVNFName)[0];
773           this.setVnfdConnectionPointRef = this.getVNFSelectedData['mgmt-cp'];
774           this.setVnfdName = this.getVNFSelectedData['product-name'];
775           this.selectedVNFProfile = getNsData.df[0]['vnf-profile'];
776         }
777       });
778     }
779     if (this.vlName !== undefined && this.setVnfdName !== undefined && this.setVnfdConnectionPointRef !== undefined) {
780       // eslint-disable-next-line security/detect-non-literal-fs-filename
781       const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
782       modalRef.componentInstance.topologyType = 'Add';
783       modalRef.componentInstance.cpDetails = this.getVNFSelectedData['ext-cpd'];
784       this.translateService.get('PAGE.TOPOLOGY.ADDINGCP', {
785         vlname: '<b>' + this.vlName + '</b>',
786         vnfdname: '<b>' + this.setVnfdName + '</b>',
787         cpname: '<b>' + this.setVnfdConnectionPointRef + '</b>'
788       }).subscribe((res: string): void => {
789         modalRef.componentInstance.topologyname = res;
790       });
791       modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.CONNECTIONPOINT');
792       modalRef.result.then((result: MODALCLOSERESPONSEWITHCP): void => {
793         if (result) {
794           this.generateCPForVNF(this.selectedVNFProfile, result.connection_point, getVLDIndex);
795           this.addData(environment.NSDESCRIPTORS_URL, this.identifier, getNsData, addType);
796         } else {
797           this.deselectPath();
798         }
799       }).catch((): void => {
800         // Catch Navigation Error
801       });
802     } else {
803       this.deselectPath();
804       this.notifierService.notify('error', this.translateService.instant('ERROR'));
805     }
806   }
807   /** Generate connection point for vnf using vld @private */
808   private generateCPForVNF(result: VNFPROFILE[], cp: string, getVLDIndex: string): void {
809     if (result !== undefined) {
810       result.forEach((resultVNFPROFILE: VNFPROFILE, index: number): void => {
811         if (getVLDIndex === resultVNFPROFILE.id) {
812           resultVNFPROFILE['virtual-link-connectivity'].push({
813             'constituent-cpd-id': [{
814               'constituent-base-element-id': getVLDIndex,
815               'constituent-cpd-id': cp
816             }],
817             'virtual-link-profile-id': this.vlName
818           });
819         }
820       });
821     } else {
822       Object.assign(result, {
823         'virtual-link-connectivity': [{
824           'constituent-cpd-id': [{
825             'constituent-base-element-id': getVLDIndex,
826             'constituent-cpd-id': cp
827           }],
828           'virtual-link-profile-id': this.vlName
829         }]
830       });
831     }
832   }
833   /** Events handles when mousedown click it will capture the selected node data @private */
834   private mouseDown(d: COMPOSERNODES): void {
835     // eslint-disable-next-line deprecation/deprecation
836     event.preventDefault();
837     if (d3.event.ctrlKey) { return; }
838     if (d3.event.shiftKey) {
839       if (d.type === 'vnfd') {
840         this.selectedNode.push(d);
841       }
842       this.mousedownNode = d;
843       this.currentSelectedNode = (this.mousedownNode === this.currentSelectedNode) ? null : this.mousedownNode;
844       this.currentSelectedLink = null;
845       this.dragLine.style('marker-end', 'url(#end-arrow)').classed('hidden', false)
846         .attr('d', `M${this.mousedownNode.x},${this.mousedownNode.y}L${this.mousedownNode.x},${this.mousedownNode.y}`);
847     }
848   }
849   /** Event handles when mouseup event occures @private */
850   private mouseUp(d: COMPOSERNODES): void {
851     if (!this.mousedownNode) { return; }
852     this.dragLine.classed('hidden', true).style('marker-end', '');
853     this.mouseupNode = d;
854     if ((this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'vnfd') ||
855       (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'vld')) {
856       if (this.mouseupNode.type === 'vnfd') {
857         this.getOldVLDIndex = this.mouseupNode.id.split(':');
858       } else if (this.mousedownNode.type === 'vnfd') {
859         this.getOldVLDIndex = this.mousedownNode.id.split(':');
860       }
861       const setOldVLDindex: string = this.getOldVLDIndex[1];
862       this.putType = 'cpAdded';
863       this.getAddConfirmation(this.mousedownNode, this.nsData, this.putType, setOldVLDindex);
864     } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'ns') {
865       this.deselectPath();
866       this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVNFCP'));
867     } else if (this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'ns') {
868       this.deselectPath();
869       this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVNFCP'));
870     } else if (this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'vld') {
871       this.deselectPath();
872       this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVL'));
873     } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'vnfd') {
874       this.deselectPath();
875       this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVNF'));
876     } else if (this.mousedownNode.type === 'ns' && this.mouseupNode.type === 'ns') {
877       this.deselectPath();
878       this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKCP'));
879     } else {
880       this.deselectPath();
881       this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVLVNF'));
882     }
883     this.resetMouseVars();
884     // select new link
885     this.currentSelectedLink = d;
886     this.currentSelectedNode = null;
887   }
888   /** Mosue Drag Line false if it is not satisfied @private */
889   private deselectPath(): void {
890     this.dragLine.classed('hidden', true).style('marker-end', '').attr('d', 'M0,0L0,0');
891   }
892   /** reset Mouse varaibles @private */
893   private resetMouseVars(): void {
894     this.mousedownNode = null;
895     this.mouseupNode = null;
896     this.mousedownLink = null;
897   }
898   /** De-select all the selected nodes @private */
899   private deselectAllNodes(): void {
900     this.vlNode.select('image').classed(this.activeClass, false);
901     this.vnfdnode.select('image').classed(this.activeClass, false);
902     this.cpnode.select('image').classed(this.activeClass, false);
903   }
904   /** Show the right-side information @private */
905   private showRightSideInfo(nsdDetails: boolean, vldDetails: boolean, vnfDeails: boolean, cpDetails: boolean): void {
906     this.isShowNSDDetails = nsdDetails;
907     this.isShowVLDetails = vldDetails;
908     this.isShowVNFDetails = vnfDeails;
909     this.isShowCPDetails = cpDetails;
910   }
911   /** Events handles when Shift Click to perform create cp @private */
912   // eslint-disable-next-line @typescript-eslint/no-explicit-any
913   private singleClick(nodeSelected: any, d: COMPOSERNODES): void {
914     this.selectNodeExclusive(nodeSelected, d);
915   }
916   /** Selected nodes @private */
917   // eslint-disable-next-line @typescript-eslint/no-explicit-any
918   private selectNodeExclusive(nodeSeleced: any, d: COMPOSERNODES): void {
919     const alreadyIsActive: boolean = nodeSeleced.select('#' + d.selectorId).classed(this.activeClass);
920     this.deselectAllNodes();
921     nodeSeleced.select('#' + d.selectorId).classed(this.activeClass, !alreadyIsActive);
922     if (d.type === 'vld' && !alreadyIsActive) {
923       this.nsData['virtual-link-desc'].forEach((result: VLD): void => {
924         if (result.id === d.id) {
925           this.showRightSideInfo(false, true, false, false);
926           this.virtualLinkDesc = result;
927         }
928       });
929     } else if (d.type === 'vnfd' && !alreadyIsActive) {
930       this.nsData.df.forEach((res: DF): void => {
931         if (res['vnf-profile'] !== undefined) {
932           res['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
933             if (resVNF.id === d.nodeIndex && resVNF['vnfd-id'] === d.name) {
934               this.showRightSideInfo(false, false, true, false);
935               this.vnfData = resVNF;
936             }
937           });
938         }
939       });
940     } else if (d.type === 'ns' && !alreadyIsActive) {
941       this.nsData.df.forEach((resultDF: DF): void => {
942         if (resultDF['vnf-profile'] !== undefined) {
943           resultDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
944             if (resVNF['virtual-link-connectivity'] !== undefined) {
945               resVNF['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => {
946                 resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => {
947                   const connectionPointID: string = resVNF.id + ':' + resultCCI['constituent-base-element-id'] + index + ':' + resultCCI['constituent-cpd-id'];
948                   if (connectionPointID === d.id) {
949                     this.cpData = resultCCI;
950                     this.vnfData = resVNF;
951                     this.virtualLinkProfileID = resultVLC['virtual-link-profile-id'];
952                     this.showRightSideInfo(false, false, false, true);
953                   }
954                 });
955               });
956             }
957           });
958         }
959       });
960     } else {
961       this.showRightSideInfo(true, false, false, false);
962     }
963   }
964   /** Get confirmation Before Deleting the Link in Topology @private */
965   private getDeleteLinkConfirmation(d: Tick): void {
966     // eslint-disable-next-line security/detect-non-literal-fs-filename
967     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
968     modalRef.componentInstance.topologyType = 'Delete';
969     modalRef.componentInstance.topologyname = this.translateService.instant('PAGE.TOPOLOGY.LINK') + ' - ' + d.source.id;
970     modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.LINK';
971     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
972       if (result) {
973         this.doubleClickLink(d);
974       }
975     }).catch((): void => {
976       // Catch Navigation Error
977     });
978   }
979   /** Events handles when Double Click to Delete the link @private */
980   private doubleClickLink(d: Tick): void {
981     let getID: string = '';
982     let getName: string = '';
983     let getNodeIndex: string;
984     if (d.source.type === 'ns') {
985       getID = d.source.id;
986       getName = d.source.name;
987       getNodeIndex = d.source.nodeIndex;
988     }
989     /** Split the selected node of connectionpoint */
990     const selectedNode: string[] = getID.split(':');
991     this.nsData.df.forEach((resultDF: DF): void => {
992       if (resultDF['vnf-profile'] !== undefined) {
993         resultDF['vnf-profile'].forEach((elementVNF: VNFPROFILE): void => {
994           const selectedVNFProfileID: string = selectedNode[0];
995           /** 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 */
996           if (selectedVNFProfileID === elementVNF.id) {
997             elementVNF['virtual-link-connectivity'].forEach((elementVLC: VLC, index: number): void => {
998               const posCCI: number = elementVLC['constituent-cpd-id'].findIndex((e: CCI): boolean => {
999                 const getCID: string = elementVNF.id + ':' + e['constituent-base-element-id'] + index + ':' + e['constituent-cpd-id'];
1000                 return getID === getCID;
1001               });
1002               if (posCCI !== -1) {
1003                 elementVNF['virtual-link-connectivity'].splice(index, 1);
1004               }
1005             });
1006           }
1007         });
1008       }
1009     });
1010     this.putType = 'linkdelete';
1011     this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
1012   }
1013   /** Get confirmation Before Deleting the Node in Topology @private */
1014   private getDeleteConfirmation(d: COMPOSERNODES): void {
1015     // eslint-disable-next-line security/detect-non-literal-fs-filename
1016     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
1017     modalRef.componentInstance.topologyType = 'Delete';
1018     modalRef.componentInstance.topologyname = d.name;
1019     if (d.type === 'vld') {
1020       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VIRTUALLINK';
1021     } else if (d.type === 'vnfd') {
1022       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VNF';
1023     } else if (d.type === 'ns') {
1024       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
1025     }
1026     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
1027       if (result) {
1028         this.doubleClick(d);
1029       }
1030     }).catch((): void => {
1031       // Catch Navigation Error
1032     });
1033   }
1034   /** Events handles when Double Click to Delete @private */
1035   private doubleClick(d: COMPOSERNODES): void {
1036     const deletedNode: COMPOSERNODES = d;
1037     this.nodes.forEach((res: COMPOSERNODES, i: number): void => {
1038       if (res.id === d.id) {
1039         if (deletedNode.type === 'vld') {
1040           /** Remove the virtual-link-desc related to VL */
1041           const pos: number = this.nsData['virtual-link-desc'].map((e: VLD): string => e.id).indexOf(d.id);
1042           this.nsData['virtual-link-desc'].splice(pos, 1);
1043           /** Remove the virtual-link-connectivity between VL and VNFD */
1044           this.nsData.df.forEach((resultDF: DF): void => {
1045             if (resultDF['vnf-profile'] !== undefined) {
1046               resultDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
1047                 const getVLArray: number[] = resVNF['virtual-link-connectivity'].map((e: VLC, index: number): number => {
1048                   if (e['virtual-link-profile-id'] === d.id) {
1049                     return index;
1050                   }
1051                 });
1052                 if (getVLArray.length > 0) {
1053                   getVLArray.forEach((removeIndex: number): void => {
1054                     const index: string = removeIndex.toString();
1055                     // eslint-disable-next-line security/detect-object-injection
1056                     resVNF['virtual-link-connectivity'].splice(resVNF['virtual-link-connectivity'][index], 1);
1057                   });
1058                 }
1059               });
1060             }
1061           });
1062           this.putType = 'nsddelete';
1063         } else if (deletedNode.type === 'vnfd') {
1064           this.nsData.df.forEach((resultDF: DF): void => {
1065             if (resultDF['vnf-profile'] !== undefined) {
1066               /** Remove the vnf-profile related to VNFD */
1067               const posVNF: number = resultDF['vnf-profile'].findIndex((e: VNFPROFILE): boolean => e['vnfd-id'] === d.name && e.id === d.nodeIndex);
1068               resultDF['vnf-profile'].splice(posVNF, 1);
1069               /** Check the VNFD exists in any vnf-profile */
1070               const isVNFDExists: boolean = resultDF['vnf-profile'].some((e: VNFPROFILE): boolean => e['vnfd-id'] === d.name);
1071               /** If VNFD not exists in the vnf-profile remove from vnfd-id */
1072               if (!isVNFDExists) {
1073                 const posVNFD: number = this.nsData['vnfd-id'].findIndex((e: string): boolean => e === d.name);
1074                 this.nsData['vnfd-id'].splice(posVNFD, 1);
1075               }
1076             }
1077           });
1078           this.putType = 'vnfddelete';
1079         } else if (deletedNode.type === 'ns') {
1080           /** Split the selected node */
1081           const selectedNode: string[] = d.id.split(':');
1082           this.nsData.df.forEach((resultDF: DF): void => {
1083             if (resultDF['vnf-profile'] !== undefined) {
1084               resultDF['vnf-profile'].forEach((elementVNF: VNFPROFILE): void => {
1085                 const selectedVNFProfileID: string = selectedNode[0];
1086                 /** 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 */
1087                 if (selectedVNFProfileID === elementVNF.id) {
1088                   elementVNF['virtual-link-connectivity'].forEach((elementVLC: VLC, index: number): void => {
1089                     const posCCI: number = elementVLC['constituent-cpd-id'].findIndex((e: CCI): boolean => {
1090                       const getID: string = elementVNF.id + ':' + e['constituent-base-element-id'] + index + ':' + e['constituent-cpd-id'];
1091                       return d.id === getID;
1092                     });
1093                     if (posCCI !== -1) {
1094                       elementVNF['virtual-link-connectivity'].splice(index, 1);
1095                     }
1096                   });
1097                 }
1098               });
1099             }
1100           });
1101           this.putType = 'nsdelete';
1102         }
1103         this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
1104       }
1105     });
1106   }
1107   /** drag event @private */
1108   // eslint-disable-next-line @typescript-eslint/no-explicit-any
1109   private onDragDrop(): any {
1110     return d3.drag().filter(this.dragFilter)
1111       .on('start', this.dragstarted)
1112       .on('drag', this.dragged)
1113       .on('end', this.dragended);
1114   }
1115   /** Key press event @private */
1116   private keyDown(): void {
1117     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
1118     if (this.lastKeyDown !== -1) { return; }
1119     this.lastKeyDown = d3.event.keyCode;
1120     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
1121       this.svg.classed('ctrl', true);
1122     }
1123   }
1124   /** Key realse event @private */
1125   private keyUp(): void {
1126     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
1127     this.lastKeyDown = -1;
1128     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
1129       this.gvlNode.on('.drag', null);
1130       this.gvnfdNode.on('.drag', null);
1131       this.gcpNode.on('.drag', null);
1132       this.svg.classed('ctrl', false);
1133     }
1134   }
1135   /** Events handles when to drag using filter for the keys @private */
1136   private dragFilter(): boolean {
1137     return d3.event.ctrlKey && !d3.event.button;
1138   }
1139   /** Events handles when dragstarted @private */
1140   private dragstarted(d: COMPOSERNODES): void {
1141     d.fx = d.x;
1142     d.fy = d.y;
1143   }
1144   /** Events handles when dragged @private */
1145   private dragged(d: COMPOSERNODES): void {
1146     d.fx = d.x = d3.event.x;
1147     d.fy = d.y = d3.event.y;
1148   }
1149   /** Events handles when dragended @private */
1150   private dragended(d: COMPOSERNODES): void {
1151     if (this.forceSimulationActive) {
1152       d.fx = null;
1153       d.fy = null;
1154     } else {
1155       d.fx = d.x;
1156       d.fy = d.y;
1157       this.forceSimulationActive = false;
1158     }
1159   }
1160   /** Events handles when node double click   @private */
1161   private onNodedblClickToggleSidebar(): void {
1162     this.sideBarOpened = false;
1163   }
1164   /** Events handles when node single click   @private */
1165   private onNodeClickToggleSidebar(): void {
1166     this.sideBarOpened = true;
1167   }
1168 }