Fix Bug 2121: NG-UI uses unmaintained Chokidar version
[osm/NG-UI.git] / src / app / packages / ns-packages / vnf-composer / VNFComposerComponent.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 VNFComposerComponent
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, ERRORDATA, MODALCLOSERESPONSEDATA } 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 { RestService } from 'RestService';
36 import { SharedService } from 'SharedService';
37 import { COMPOSERNODES, EXTCPD, GRAPHDETAILS, INTCPD, IVLD, Tick, TickPath, VDU, VDUINTCPD, VNFD, VNFDATA, VNIR } from 'VNFDModel';
38
39 /**
40  * Creating component
41  * @Component takes VNFComposerComponent.html as template url
42  */
43 @Component({
44   templateUrl: './VNFComposerComponent.html',
45   styleUrls: ['./VNFComposerComponent.scss'],
46   encapsulation: ViewEncapsulation.None
47 })
48 /** Exporting a class @exports VNFComposerComponent */
49 export class VNFComposerComponent {
50   /** To inject services @public */
51   public injector: Injector;
52   /** View child contains graphContainer ref @public  */
53   @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
54   /** dataService to pass the data from one component to another @public */
55   public dataService: DataService;
56   /** random number count @public */
57   public randomNumberLength: number;
58   /** Contains the vnfd information @public */
59   public vnfList: string[] = [];
60   /** Contains VNFD Information @public */
61   public vnfdInfo: VNFD = { 'product-name': '', description: '', version: '', id: '', provider: '' };
62   /** Contains right panel box information @public */
63   public showRightSideInfo: string = '';
64   /** Add the fixed class for the freeze @public */
65   public fixedClass: string = 'fixed';
66   /** Check the loading results @public */
67   public isLoadingResults: boolean = true;
68   /** Give the message for the loading @public */
69   public message: string = 'PLEASEWAIT';
70   /** Assign the forcesimulation active @public */
71   public forceSimulationActive: boolean = false;
72   /** Assign pinned class for the button when freezed @public */
73   public classApplied: boolean = false;
74   /** Contains sidebar open status @public */
75   public sideBarOpened: boolean = false;
76   /** Contains SVG attributes @private */
77   // eslint-disable-next-line @typescript-eslint/no-explicit-any
78   private svg: any;
79   /** Contains forced node animations @private */
80   // eslint-disable-next-line @typescript-eslint/no-explicit-any
81   private force: any;
82   /** Contains the Drag line */
83   // eslint-disable-next-line @typescript-eslint/no-explicit-any
84   private dragLine: any;
85   /** Contains id of the node @private */
86   private identifier: string;
87   /** Contains path information of the node */
88   // eslint-disable-next-line @typescript-eslint/no-explicit-any
89   private path: any;
90   /** Contains node network @private */
91   // eslint-disable-next-line @typescript-eslint/no-explicit-any
92   private network: any;
93   /** Contains node network @private */
94   // eslint-disable-next-line @typescript-eslint/no-explicit-any
95   private virutualDeploymentUnit: any;
96   /** Contains node connectionPoint @private */
97   // eslint-disable-next-line @typescript-eslint/no-explicit-any
98   private connectionPoint: any;
99   /** Contains node intConnectionPoint @private */
100   // eslint-disable-next-line @typescript-eslint/no-explicit-any
101   private intConnectionPoint: any;
102   /** Contains the node information @private */
103   private nodes: COMPOSERNODES[] = [];
104   /** Contains the link information of nodes @private */
105   private links: {}[] = [];
106   /** Instance of the rest service @private */
107   private restService: RestService;
108   /** Service holds the router information @private */
109   private router: Router;
110   /** Service contails all the shared service information @private */
111   private sharedService: SharedService;
112   /** Holds teh instance of AuthService class of type AuthService @private */
113   private activatedRoute: ActivatedRoute;
114   /** Notifier service to popup notification @private */
115   private notifierService: NotifierService;
116   /** Controls the header form @private */
117   private headers: HttpHeaders;
118   /** Contains tranlsate instance @private */
119   private translateService: TranslateService;
120   /** Rendered nodes represent network @private */
121   // eslint-disable-next-line @typescript-eslint/no-explicit-any
122   private gNetwork: any;
123   /** Rendered nodes represent VDU @private */
124   // eslint-disable-next-line @typescript-eslint/no-explicit-any
125   private gVirutualDeploymentUnit: any;
126   /** Rendered nodes represent connection point @private */
127   // eslint-disable-next-line @typescript-eslint/no-explicit-any
128   private gConnectionPoint: any;
129   /** Rendered nodes represent internal connection point @private */
130   // eslint-disable-next-line @typescript-eslint/no-explicit-any
131   private gIntConnectionPoint: any;
132   /** Contains all the information about VNF Details @private */
133   private vnfdPackageDetails: VNFD;
134   /** Conatins mousedown action @private */
135   private mousedownNode: COMPOSERNODES = null;
136   /** Conatins mouseup action @private */
137   private mouseupNode: COMPOSERNODES = null;
138   /** Conatins current Selection node action @private */
139   private currentSelectedNode: COMPOSERNODES = null;
140   /** Add the activeNode for the selected @private */
141   private activeNode: string = 'active';
142   /** Contains lastkeypressed instance @private */
143   private lastKeyDown: number = -1;
144   /** Contains VDU Information @private */
145   private vduInfo: VDU;
146   /** Contains VDU Old value Information @private */
147   private oldVDUID: string;
148   /** Contains Internal VL Information @private */
149   private intvlInfo: IVLD;
150   /** Contains Internal VL Old value Information @private */
151   private oldintVLID: string;
152   /** Contains Connection Point Information @private */
153   private cpInfo: EXTCPD;
154   /** Contains Connection Point Old value Information @private */
155   private oldCPID: string;
156   /** Contains Internal Connection Point Information @private */
157   private intcpInfo: VNIR;
158   /** Instance of the modal service @private */
159   private modalService: NgbModal;
160
161   constructor(injector: Injector) {
162     this.injector = injector;
163     this.restService = this.injector.get(RestService);
164     this.dataService = this.injector.get(DataService);
165     this.router = this.injector.get(Router);
166     this.activatedRoute = this.injector.get(ActivatedRoute);
167     this.notifierService = this.injector.get(NotifierService);
168     this.translateService = this.injector.get(TranslateService);
169     this.sharedService = this.injector.get(SharedService);
170     this.modalService = this.injector.get(NgbModal);
171   }
172   /**
173    * Lifecyle Hooks the trigger before component is instantiate
174    */
175   public ngOnInit(): void {
176     this.identifier = this.activatedRoute.snapshot.paramMap.get('id');
177     this.generateData();
178     this.headers = new HttpHeaders({
179       'Content-Type': 'application/gzip',
180       Accept: 'application/json',
181       'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
182     });
183   }
184
185   /** Prepare information for node creation of VNFD @public */
186   public generateData(): void {
187     this.nodes = []; this.links = []; this.vnfdPackageDetails = null;
188     this.showRightSideInfo = 'vnfdInfo';
189     this.restService.getResource(environment.VNFPACKAGESCONTENT_URL + '/' + this.identifier)
190       .subscribe((vnfdPackageDetails: VNFD): void => {
191         try {
192           delete vnfdPackageDetails._admin;
193           delete vnfdPackageDetails._id;
194           delete vnfdPackageDetails._links;
195           this.vnfdPackageDetails = vnfdPackageDetails;
196           this.generateVDU(vnfdPackageDetails);
197           this.generateCPPoint(vnfdPackageDetails);
198           this.generateInternalVLD(vnfdPackageDetails);
199           this.generateInternalCP(vnfdPackageDetails);
200           this.generateIntVLCPLinks(vnfdPackageDetails);
201           this.generateVDUCPLinks(vnfdPackageDetails);
202           this.createNode(this.nodes);
203           this.generateVNFInfo(vnfdPackageDetails);
204         } catch (e) {
205           this.notifierService.notify('error', this.translateService.instant('ERROR'));
206         }
207         this.isLoadingResults = false;
208       }, (error: ERRORDATA): void => {
209         error.error = typeof error.error === 'string' ? jsyaml.load(error.error) : error.error;
210         if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
211           this.router.navigateByUrl('404', { skipLocationChange: true }).catch((): void => {
212             // Catch Navigation Error
213         });
214         } else {
215           this.restService.handleError(error, 'get');
216         }
217         this.isLoadingResults = false;
218         this.showRightSideInfo = '';
219       });
220   }
221   /** Generate the VNF Package Information */
222   public generateVNFInfo(vnfdPackageDetails: VNFD): void {
223     this.vnfdInfo['product-name'] = vnfdPackageDetails['product-name'];
224     this.vnfdInfo.description = vnfdPackageDetails.description;
225     this.vnfdInfo.version = vnfdPackageDetails.version;
226     this.vnfdInfo.id = vnfdPackageDetails.id;
227     this.vnfdInfo.provider = vnfdPackageDetails.provider;
228   }
229   /** Events handles at drag on D3 region @public */
230   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
231   public drag(ev: any): void {
232     ev.dataTransfer.setData('text', ev.target.id);
233   }
234   /** Events handles drop at D3 region @public */
235   public drop(ev: DragEvent): void {
236     ev.preventDefault();
237     const getDropedName: string = ev.dataTransfer.getData('text');
238     if (getDropedName === 'vdu') {
239       this.svg.selectAll('*').remove();
240       this.vduDropCompose();
241     } else if (getDropedName === 'cp') {
242       this.svg.selectAll('*').remove();
243       this.cpDropCompose();
244     } else if (getDropedName === 'intvl') {
245       this.svg.selectAll('*').remove();
246       this.intvlDropCompose();
247     }
248   }
249   /** Events handles allow drop on D3 region @public */
250   public allowDrop(ev: DragEvent): void {
251     ev.preventDefault();
252   }
253   /** Generate and list VDU @public */
254   public generateVDU(vnfdPackageDetails: VNFD): void {
255     if (vnfdPackageDetails.vdu !== undefined) {
256       vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
257         this.nodes.push({
258           id: vdu.id,
259           name: vdu.name,
260           reflexive: false,
261           type: 'vdu'
262         });
263       });
264     }
265   }
266   /** Generate and list CP points @public */
267   public generateCPPoint(vnfdPackageDetails: VNFD): void {
268     if (vnfdPackageDetails['ext-cpd'] !== undefined) {
269       vnfdPackageDetails['ext-cpd'].forEach((cp: EXTCPD): void => {
270         this.nodes.push({
271           id: cp['int-cpd'].cpd !== undefined ? cp['int-cpd'].cpd : cp.id,
272           name: cp.id,
273           reflexive: false,
274           type: 'cp'
275         });
276       });
277     }
278   }
279   /** Generate and list Internal VLD @public */
280   public generateInternalVLD(vnfdPackageDetails: VNFD): void {
281     if (vnfdPackageDetails['int-virtual-link-desc'] !== undefined) {
282       vnfdPackageDetails['int-virtual-link-desc'].forEach((ivld: IVLD): void => {
283         this.nodes.push({
284           id: ivld.id,
285           name: ivld.id,
286           reflexive: false,
287           type: 'intvl'
288         });
289       });
290     }
291   }
292   /** Generate and list Internal CP @public */
293   public generateInternalCP(vnfdPackageDetails: VNFD): void {
294     if (vnfdPackageDetails.vdu !== undefined) {
295       vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
296         if (vdu['int-cpd'] !== undefined) {
297           vdu['int-cpd'].forEach((intcpd: VDUINTCPD): void => {
298             if (intcpd['int-virtual-link-desc'] !== undefined) {
299               intcpd['virtual-network-interface-requirement'].forEach((vnir: VNIR): void => {
300                 this.nodes.push({
301                   id: intcpd.id,
302                   name: vnir.name,
303                   reflexive: false,
304                   type: 'intcp'
305                 });
306               });
307             }
308           });
309         }
310       });
311     }
312   }
313   /** Generate VDU External and Internal CP Links @public */
314   public generateVDUCPLinks(vnfdPackageDetails: VNFD): void {
315     if (vnfdPackageDetails.vdu !== undefined) {
316       vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
317         const vduLink: string = vdu.id;
318         if (vdu['int-cpd'] !== undefined) {
319           vdu['int-cpd'].forEach((intCPD: VDUINTCPD): void => {
320             if (intCPD['int-virtual-link-desc'] !== undefined) {
321               intCPD['virtual-network-interface-requirement'].forEach((vnir: VNIR): void => {
322                 this.links.push({ source: vduLink, target: intCPD.id });
323               });
324             } else {
325               this.links.push({ source: vduLink, target: intCPD.id });
326             }
327           });
328         }
329       });
330     }
331   }
332   /** Generate Network/VLD/Internal VirtualLink, CP Links @public */
333   public generateIntVLCPLinks(vnfdPackageDetails: VNFD): void {
334     if (vnfdPackageDetails.vdu !== undefined) {
335       vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
336         if (vdu['int-cpd'] !== undefined) {
337           vdu['int-cpd'].forEach((intCPD: VDUINTCPD): void => {
338             const vldName: string = intCPD['int-virtual-link-desc'];
339             if (intCPD['int-virtual-link-desc'] !== undefined) {
340               intCPD['virtual-network-interface-requirement'].forEach((vnir: VNIR): void => {
341                 this.links.push({ source: vldName, target: intCPD.id });
342               });
343             }
344           });
345         }
346       });
347     }
348   }
349   /** VNFD details can be saved on users inputs @public */
350   public saveVNFD(): void {
351     this.vnfdPackageDetails['product-name'] = this.vnfdInfo['product-name'];
352     this.vnfdPackageDetails.description = this.vnfdInfo.description;
353     this.vnfdPackageDetails.version = this.vnfdInfo.version;
354     this.vnfdPackageDetails.id = this.vnfdInfo.id;
355     this.vnfdPackageDetails.provider = this.vnfdInfo.provider;
356     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
357   }
358   /** VDU details can be saved on users inputs @public */
359   public saveVDU(getVDUID: string): void {
360     const getOLDVDUID: string = this.oldVDUID;
361     this.vnfdPackageDetails.vdu.forEach((ref: VDU): void => {
362       if (ref.id === getVDUID) {
363         ref.id = this.vduInfo.id;
364         ref.name = this.vduInfo.name;
365         ref.description = this.vduInfo.description !== undefined ? this.vduInfo.description : '';
366         ref['sw-image-desc'] = this.vduInfo['sw-image-desc'];
367       }
368     });
369     this.vnfdPackageDetails['ext-cpd'].forEach((extCPD: EXTCPD): void => {
370       if (extCPD['int-cpd'] !== undefined) {
371         if (extCPD['int-cpd']['vdu-id'] === getOLDVDUID) {
372           extCPD['int-cpd']['vdu-id'] = this.vduInfo.id;
373         }
374       }
375     });
376     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
377   }
378   /** IntVL details can be saved on users inputs @public */
379   public saveIntVL(intVLID: string): void {
380     const getOldID: string = this.oldintVLID;
381     this.vnfdPackageDetails['int-virtual-link-desc'].forEach((ivldDetails: IVLD): void => {
382       if (ivldDetails.id === intVLID) {
383         ivldDetails.id = this.intvlInfo.id;
384       }
385     });
386     this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU): void => {
387       if (vduDetails['int-cpd'] !== undefined) {
388         vduDetails['int-cpd'].forEach((intCPDDetails: VDUINTCPD): void => {
389           if (intCPDDetails['int-virtual-link-desc'] !== undefined) {
390             if (intCPDDetails['int-virtual-link-desc'] === getOldID) {
391               intCPDDetails['int-virtual-link-desc'] = this.intvlInfo.id;
392             }
393           }
394         });
395       }
396     });
397     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
398   }
399   /** IntVL details can be saved on users inputs @public */
400   public saveCP(cpID: string): void {
401     const getOldCP: string = this.oldCPID;
402     this.vnfdPackageDetails['ext-cpd'].forEach((ref: EXTCPD): void => {
403       if (ref.id === cpID) {
404         ref.id = this.cpInfo.id;
405       }
406     });
407     if (this.vnfdPackageDetails['mgmt-cp'] === getOldCP) {
408       this.vnfdPackageDetails['mgmt-cp'] = this.cpInfo.id;
409     }
410     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
411   }
412   /** Edit topology @public */
413   public onEdit(): void {
414     this.router.navigate(['/packages/vnf/edit/', this.identifier]).catch((): void => {
415       // Catch Navigation Error
416   });
417   }
418   /** Show Info @public */
419   public showInfo(): void {
420     // eslint-disable-next-line security/detect-non-literal-fs-filename
421     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
422     modalRef.componentInstance.topologyType = 'Info';
423     modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.INFO');
424     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
425       if (result) {
426         // empty
427       }
428     }).catch((): void => {
429       // Catch Navigation Error
430   });
431   }
432   /** Event to freeze the animation @public */
433   public onFreeze(): void {
434     this.classApplied = !this.classApplied;
435     const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
436     d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
437     if (alreadyFixedIsActive) {
438       this.force.stop();
439     }
440     this.forceSimulationActive = alreadyFixedIsActive;
441     this.nodes.forEach((d: COMPOSERNODES): void => {
442       d.fx = (alreadyFixedIsActive) ? null : d.x;
443       d.fy = (alreadyFixedIsActive) ? null : d.y;
444     });
445     if (alreadyFixedIsActive) {
446       this.force.restart();
447     }
448   }
449   /** Events handles when dragended @public */
450   public toggleSidebar(): void {
451     this.sideBarOpened = !this.sideBarOpened;
452     this.deselectAllNodes();
453     this.showRightSideInfo = 'vnfdInfo';
454   }
455   /** Get the default Configuration of containers @private */
456   private getGraphContainerAttr(): GRAPHDETAILS {
457     return {
458       width: 700,
459       height: 400,
460       nodeHeight: 50,
461       nodeWidth: 35,
462       textX: -35,
463       textY: 30,
464       radius: 5,
465       distance: 50,
466       strength: -500,
467       forcex: 2,
468       forcey: 2,
469       sourcePaddingYes: 17,
470       sourcePaddingNo: 12,
471       targetPaddingYes: 4,
472       targetPaddingNo: 3,
473       alphaTarget: 0.3,
474       imageX: -25,
475       imageY: -25,
476       shiftKeyCode: 17
477     };
478   }
479   /** Node is created and render at D3 region @private */
480   private createNode(nodes: VNFD[]): void {
481     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
482     d3.selectAll('svg#graphContainer > *').remove();
483     d3.select(window).on('keydown', (): void => { this.keyDown(); });
484     d3.select(window).on('keyup', (): void => { this.keyUp(); });
485     this.svg = d3.select('#graphContainer')
486       .attr('oncontextmenu', 'return false;')
487       .attr('viewBox', `0 0 ${graphContainerAttr.width} ${graphContainerAttr.height}`)
488       .on('mousemove', (): void => { this.mousemove(); });
489     this.force = d3.forceSimulation()
490       .force('link', d3.forceLink().id((d: TickPath): string => d.id).distance(graphContainerAttr.distance))
491       .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
492       .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
493       .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
494       .on('tick', (): void => { this.tick(); });
495     this.path = this.svg.append('svg:g').selectAll('path');
496     this.dragLine = this.svg.append('svg:path').attr('class', 'link dragline hidden').attr('d', 'M0,0L0,0');
497     this.network = this.svg.append('svg:g').selectAll('network');
498     this.virutualDeploymentUnit = this.svg.append('svg:g').selectAll('virutualDeploymentUnit');
499     this.connectionPoint = this.svg.append('svg:g').selectAll('connectionPoint');
500     this.intConnectionPoint = this.svg.append('svg:g').selectAll('intConnectionPoint');
501     this.restart(nodes);
502   }
503   /** Update force layout (called automatically each iteration) @private */
504   private tick(): void {
505     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
506     this.path.attr('d', (d: Tick): string => {
507       const deltaX: number = d.target.x - d.source.x; const deltaY: number = d.target.y - d.source.y;
508       const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
509       const normX: number = deltaX / dist; const normY: number = deltaY / dist;
510       const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
511       const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
512       const sourceX: number = d.source.x + (sourcePadding * normX); const sourceY: number = d.source.y + (sourcePadding * normY);
513       const targetX: number = d.target.x - (targetPadding * normX); const targetY: number = d.target.y - (targetPadding * normY);
514       return `M${sourceX},${sourceY}L${targetX},${targetY}`;
515     }).on('dblclick', (d: Tick): void => { this.getDeleteLinkConfirmation(d); });
516     this.network.attr('transform', (d: TickPath): string => `translate(${d.x},${d.y})`);
517     this.virutualDeploymentUnit.attr('transform', (d: TickPath): string => `translate(${d.x},${d.y})`);
518     this.connectionPoint.attr('transform', (d: TickPath): string => `translate(${d.x},${d.y})`);
519     this.intConnectionPoint.attr('transform', (d: TickPath): string => `translate(${d.x},${d.y})`);
520   }
521   /** Update graph (called when needed) @private */
522   private restart(nodes: VNFD[]): void {
523     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
524     this.path = this.path.data(this.links);
525     const cpNodes: {}[] = []; const vduNodes: {}[] = []; const vlNodes: {}[] = []; const intcpNodes: {}[] = []; //Nodes are known by id
526     nodes.forEach((nodeList: COMPOSERNODES): void => {
527       if (nodeList.type === 'cp') { cpNodes.push(nodeList); }
528       else if (nodeList.type === 'vdu') { vduNodes.push(nodeList); }
529       else if (nodeList.type === 'intvl') { vlNodes.push(nodeList); }
530       else if (nodeList.type === 'intcp') { intcpNodes.push(nodeList); }
531     });
532     this.network = this.network.data(vlNodes, (d: VNFD): string => d.id);
533     this.virutualDeploymentUnit = this.virutualDeploymentUnit.data(vduNodes, (d: VNFD): string => d.id);
534     this.connectionPoint = this.connectionPoint.data(cpNodes, (d: VNFD): string => d.id);
535     this.intConnectionPoint = this.intConnectionPoint.data(intcpNodes, (d: VNFD): string => d.id);
536     this.resetAndCreateNodes();
537     this.force.nodes(nodes).force('link').links(this.links); //Set the graph in motion
538     this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
539   }
540   /** Rest and create nodes @private */
541   private resetAndCreateNodes(): void {
542     this.path.exit().remove();
543     this.network.exit().remove();
544     this.virutualDeploymentUnit.exit().remove();
545     this.connectionPoint.exit().remove();
546     this.intConnectionPoint.exit().remove();
547     this.getPathNodes();
548     this.getgNetwork();
549     this.getgVirutualDeploymentUnit();
550     this.getgConnectionPoint();
551     this.getgIntConnectionPoint();
552     this.network = this.gNetwork.merge(this.network);
553     this.virutualDeploymentUnit = this.gVirutualDeploymentUnit.merge(this.virutualDeploymentUnit);
554     this.connectionPoint = this.gConnectionPoint.merge(this.connectionPoint);
555     this.intConnectionPoint = this.gIntConnectionPoint.merge(this.intConnectionPoint);
556     this.path.merge(this.path);
557   }
558   /** Setting the Path @private */
559   private getPathNodes(): void {
560     this.path = this.path.enter().append('svg:path').attr('class', 'link');
561   }
562   /** Settings all the network attributes of nodes @private */
563   private getgNetwork(): void {
564     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
565     this.gNetwork = this.network.enter().append('svg:g');
566     this.gNetwork.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
567     this.gNetwork.append('svg:image')
568       .style('opacity', 1)
569       .attr('x', graphContainerAttr.imageX)
570       .attr('y', graphContainerAttr.imageY)
571       .call(this.onDragDrop())
572       .attr('id', (d: COMPOSERNODES): string => d.id)
573       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
574       .attr('xlink:href', 'assets/images/INTVL.svg')
575       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
576       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
577       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.network, d); this.onNodeClickToggleSidebar(); })
578       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
579     this.gNetwork.append('svg:text')
580       .attr('class', 'node_text')
581       .attr('y', graphContainerAttr.textY)
582       .text((d: COMPOSERNODES): string => d.id);
583   }
584   /** Settings all the connection point attributes of nodes @private */
585   private getgVirutualDeploymentUnit(): void {
586     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
587     this.gVirutualDeploymentUnit = this.virutualDeploymentUnit.enter().append('svg:g');
588     this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
589     this.gVirutualDeploymentUnit.append('svg:image')
590       .style('opacity', 1)
591       .attr('x', graphContainerAttr.imageX)
592       .attr('y', graphContainerAttr.imageY)
593       .call(this.onDragDrop())
594       .attr('id', (d: COMPOSERNODES): string => d.id)
595       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
596       .attr('xlink:href', 'assets/images/VDU.svg')
597       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
598       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
599       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.virutualDeploymentUnit, d); this.onNodeClickToggleSidebar(); })
600       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
601     this.gVirutualDeploymentUnit.append('svg:text')
602       .attr('class', 'node_text')
603       .attr('y', graphContainerAttr.textY)
604       .text((d: COMPOSERNODES): string => d.id);
605   }
606   /** Settings all the connection point attributes of nodes @private */
607   private getgConnectionPoint(): void {
608     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
609     this.gConnectionPoint = this.connectionPoint.enter().append('svg:g');
610     this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
611     this.gConnectionPoint.append('svg:image')
612       .style('opacity', 1)
613       .attr('x', graphContainerAttr.imageX)
614       .attr('y', graphContainerAttr.imageY)
615       .call(this.onDragDrop())
616       .attr('id', (d: COMPOSERNODES): string => d.id)
617       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
618       .attr('xlink:href', 'assets/images/CP-VNF.svg')
619       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
620       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
621       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.connectionPoint, d); this.onNodeClickToggleSidebar(); })
622       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
623     this.gConnectionPoint.append('svg:text')
624       .attr('class', 'node_text')
625       .attr('y', graphContainerAttr.textY)
626       .text((d: COMPOSERNODES): string => d.name);
627   }
628   /** Settings all the internal connection point attributes of nodes @private */
629   private getgIntConnectionPoint(): void {
630     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
631     this.gIntConnectionPoint = this.intConnectionPoint.enter().append('svg:g');
632     this.gIntConnectionPoint.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
633     this.gIntConnectionPoint.append('svg:image')
634       .style('opacity', 1)
635       .attr('x', graphContainerAttr.imageX)
636       .attr('y', graphContainerAttr.imageY)
637       .call(this.onDragDrop())
638       .attr('id', (d: COMPOSERNODES): string => d.id)
639       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
640       .attr('xlink:href', 'assets/images/INTCP.svg')
641       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
642       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
643       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.intConnectionPoint, d); this.onNodeClickToggleSidebar(); })
644       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
645     this.gIntConnectionPoint.append('svg:text')
646       .attr('class', 'node_text')
647       .attr('y', graphContainerAttr.textY)
648       .text((d: COMPOSERNODES): string => d.name);
649   }
650   /** Drop VDU Composer Data @private */
651   private vduDropCompose(): void {
652     const randomID: string = this.sharedService.randomString();
653     if (this.vnfdPackageDetails['mgmt-cp'] === undefined) {
654       this.notifierService.notify('error', this.translateService.instant('PAGE.TOPOLOGY.ADDCPBEFOREVDU'));
655     } else {
656       if (this.vnfdPackageDetails.vdu === undefined) {
657         this.vnfdPackageDetails.vdu = [];
658       }
659       this.vnfdPackageDetails.vdu.push({
660         id: 'vdu_' + randomID,
661         name: 'vdu_' + randomID,
662         description: '',
663         'sw-image-desc': 'ubuntu',
664         'int-cpd': [],
665         'monitoring-parameter': [],
666         'virtual-compute-desc': '',
667         'virtual-storage-desc': []
668       });
669       this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
670     }
671   }
672   /** Drop CP Composer Data @private */
673   private cpDropCompose(): void {
674     const randomID: string = this.sharedService.randomString();
675     if (this.vnfdPackageDetails['ext-cpd'] === undefined) {
676       this.vnfdPackageDetails['ext-cpd'] = [];
677     }
678     this.vnfdPackageDetails['ext-cpd'].push({
679       id: 'cp_' + randomID,
680       'int-cpd': {}
681     });
682     if (this.vnfdPackageDetails['mgmt-cp'] === undefined) {
683       this.vnfdPackageDetails['mgmt-cp'] = 'cp_' + randomID;
684     }
685     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
686   }
687   /** Drop IntVL Composer Data @private */
688   private intvlDropCompose(): void {
689     const randomID: string = this.sharedService.randomString();
690     if (this.vnfdPackageDetails['int-virtual-link-desc'] === undefined) {
691       this.vnfdPackageDetails['int-virtual-link-desc'] = [];
692     }
693     this.vnfdPackageDetails['int-virtual-link-desc'].push({
694       id: 'vnf_vl_' + randomID
695     });
696     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
697   }
698   /** Add the Add Nodes Data @private */
699   private addNodes(apiURL: string, identifier: string, data: VNFD): void {
700     this.isLoadingResults = true;
701     const apiURLHeader: APIURLHEADER = {
702       url: apiURL + '/' + identifier + '/package_content',
703       httpOptions: { headers: this.headers }
704     };
705     const vnfData: VNFDATA = {};
706     vnfData.vnfd = data;
707     const descriptorInfo: string = jsyaml.dump(vnfData, { sortKeys: true });
708     this.sharedService.targzFile({ packageType: 'vnfd', id: this.identifier, descriptor: descriptorInfo })
709       .then((content: ArrayBuffer): void => {
710         this.restService.putResource(apiURLHeader, content).subscribe((res: {}): void => {
711           this.generateData();
712           this.notifierService.notify('success', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.UPDATEDSUCCESSFULLY'));
713           this.isLoadingResults = false;
714         }, (error: ERRORDATA): void => {
715           this.generateData();
716           this.restService.handleError(error, 'put');
717           this.isLoadingResults = false;
718         });
719       }).catch((): void => {
720         this.notifierService.notify('error', this.translateService.instant('ERROR'));
721         this.isLoadingResults = false;
722       });
723   }
724   /** Events handles when mousedown click it will capture the selected node data @private */
725   private mouseDown(d: COMPOSERNODES): void {
726     // eslint-disable-next-line deprecation/deprecation
727     event.preventDefault();
728     if (d3.event.ctrlKey) { return; }
729     if (d3.event.shiftKey) {
730       this.mousedownNode = d;
731       this.currentSelectedNode = (this.mousedownNode === this.currentSelectedNode) ? null : this.mousedownNode;
732       this.dragLine.classed('hidden', false)
733         .attr('d', `M${this.mousedownNode.x},${this.mousedownNode.y}L${this.mousedownNode.x},${this.mousedownNode.y}`);
734     }
735   }
736   /** Event handles when mouseup event occures @private */
737   private mouseUp(d: COMPOSERNODES): void {
738     if (!this.mousedownNode) { return; }
739     this.dragLine.classed('hidden', true);
740     this.mouseupNode = d;
741     if (this.mousedownNode.type === 'vdu') {
742       this.vduMouseDownNode();
743     } else if (this.mousedownNode.type === 'cp') {
744       this.cpMouseDownNode();
745     } else if (this.mousedownNode.type === 'intvl') {
746       this.intVLMouseDownNode();
747     } else if (this.mousedownNode.type === 'intcp') {
748       this.intCPMouseDownNode();
749     } else {
750       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
751       this.deselectPath();
752     }
753     this.resetMouseActions();
754     this.currentSelectedNode = null;
755   }
756   /** Establish a connection point between vdu and other nodes @private */
757   private vduMouseDownNode(): void {
758     if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'cp') {
759       this.vduCPConnection(this.mousedownNode.id, this.mouseupNode.id);
760     } else if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'intcp') {
761       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDINTCP'));
762       this.deselectPath();
763     } else if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'vdu') {
764       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDVDU'));
765       this.deselectPath();
766     } else if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'intvl') {
767       this.vduIntvlConnection(this.mousedownNode.id, this.mouseupNode.id);
768     }
769   }
770   /** Establish a connection point between cp and other nodes @private */
771   private cpMouseDownNode(): void {
772     if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'vdu') {
773       this.vduCPConnection(this.mouseupNode.id, this.mousedownNode.id);
774     } else if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'intvl') {
775       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDVNFVL'));
776       this.deselectPath();
777     } else if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'intcp') {
778       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDINTCP'));
779       this.deselectPath();
780     } else if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'cp') {
781       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDCP'));
782       this.deselectPath();
783     }
784   }
785   /** Establish a connection piont between intvl and other nodes @private */
786   private intVLMouseDownNode(): void {
787     if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'cp') {
788       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDCP'));
789       this.deselectPath();
790     } else if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'vdu') {
791       this.vduIntvlConnection(this.mouseupNode.id, this.mousedownNode.id);
792     } else if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'intvl') {
793       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDVNFVL'));
794       this.deselectPath();
795     } else if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'intcp') {
796       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDONTCP'));
797       this.deselectPath();
798     }
799   }
800   /** Establish a connection point between intcp and other nodes @private */
801   private intCPMouseDownNode(): void {
802     if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'vdu') {
803       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVDU'));
804       this.deselectPath();
805     } else if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'cp') {
806       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDCP'));
807       this.deselectPath();
808     } else if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'intvl') {
809       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVNFVL'));
810       this.deselectPath();
811     } else if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'intcp') {
812       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDINTCP'));
813       this.deselectPath();
814     }
815   }
816   /** Establish a connection between VDU & CP vice versa @private */
817   private vduCPConnection(nodeA: string, nodeB: string): void {
818     const vduExternalID: string = nodeA + '-eth_' + this.sharedService.randomString();
819     if (this.vnfdPackageDetails.vdu !== undefined) {
820       this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
821         const vduID: string = vdu.id;
822         if (vdu.id === nodeA) {
823           if (this.vnfdPackageDetails['ext-cpd'] !== undefined) {
824             this.vnfdPackageDetails['ext-cpd'].forEach((extcpd: EXTCPD, index: number): void => {
825               if (extcpd.id === nodeB) {
826                 if (vdu['int-cpd'] === undefined) {
827                   vdu['int-cpd'] = [];
828                 }
829                 vdu['int-cpd'].push({
830                   id: vduExternalID,
831                   'virtual-network-interface-requirement': [
832                     {
833                       name: vduExternalID,
834                       position: 1,
835                       'virtual-interface': { type: 'PARAVIRT' }
836                     }
837                   ]
838                 });
839                 // eslint-disable-next-line security/detect-object-injection
840                 this.vnfdPackageDetails['ext-cpd'][index] = {
841                   id: extcpd.id,
842                   'int-cpd': {
843                     cpd: vduExternalID,
844                     'vdu-id': vduID
845                   }
846                 };
847               }
848             });
849           }
850         }
851       });
852     }
853     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
854     this.deselectPath();
855   }
856   /** Establish a connection between vdu & intvl and vice versa @private */
857   private vduIntvlConnection(nodeA: string, nodeB: string): void {
858     const vduInternalID: string = nodeA + '-eth_' + this.sharedService.randomString();
859     if (this.vnfdPackageDetails.vdu !== undefined) {
860       this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
861         if (vdu.id === nodeA) {
862           if (vdu['int-cpd'] === undefined) {
863             vdu['int-cpd'] = [];
864           }
865           vdu['int-cpd'].push({
866             id: vduInternalID,
867             'int-virtual-link-desc': nodeB,
868             'virtual-network-interface-requirement': [
869               {
870                 name: vduInternalID,
871                 position: 1,
872                 'virtual-interface': { type: 'PARAVIRT' }
873               }
874             ]
875           });
876         }
877       });
878     }
879     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
880     this.deselectPath();
881   }
882   /** Events handles when mousemove it will capture the selected node data @private */
883   private mousemove(): void {
884     if (!this.mousedownNode) { return; }
885     this.dragLine.attr('d',
886       `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
887   }
888   /** reset Mouse varaibles @private */
889   private resetMouseActions(): void {
890     this.mousedownNode = null;
891     this.mouseupNode = null;
892   }
893   /** drag event @private */
894   // eslint-disable-next-line @typescript-eslint/no-explicit-any
895   private onDragDrop(): any {
896     return d3.drag().filter(this.dragFilter)
897       .on('start', this.dragstarted)
898       .on('drag', this.dragged)
899       .on('end', this.dragended);
900   }
901   /** Key press event @private */
902   private keyDown(): void {
903     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
904     if (this.lastKeyDown !== -1) { return; }
905     this.lastKeyDown = d3.event.keyCode;
906     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
907       this.svg.classed('ctrl', true);
908     }
909   }
910   /** Key realse event @private */
911   private keyUp(): void {
912     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
913     this.lastKeyDown = -1;
914     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
915       this.gNetwork.on('.drag', null);
916       this.gVirutualDeploymentUnit.on('.drag', null);
917       this.gConnectionPoint.on('.drag', null);
918       this.gIntConnectionPoint.on('.drag', null);
919       this.svg.classed('ctrl', false);
920     }
921   }
922   /** Mosue Drag Line false if it is not satisfied @private */
923   private deselectPath(): void {
924     this.dragLine.classed('hidden', true).attr('d', 'M0,0L0,0');
925   }
926   /** Events handles when Shift Click to perform create cp @private */
927   // eslint-disable-next-line @typescript-eslint/no-explicit-any
928   private singleClick(nodeSelected: any, d: COMPOSERNODES): void {
929     this.selectedNode(nodeSelected, d);
930   }
931   /** Get confirmation Before Deleting the Node in Topology @private */
932   private getDeleteNodeConfirmation(d: COMPOSERNODES): void {
933     // eslint-disable-next-line security/detect-non-literal-fs-filename
934     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
935     modalRef.componentInstance.topologyType = 'Delete';
936     modalRef.componentInstance.topologyname = d.name;
937     if (d.type === 'vdu') {
938       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VDU';
939     } else if (d.type === 'intvl') {
940       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTVL';
941     } else if (d.type === 'cp') {
942       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
943     } else if (d.type === 'intcp') {
944       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTCP';
945     }
946     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
947       if (result) {
948         this.deleteNode(d);
949       }
950     }).catch((): void => {
951       // Catch Navigation Error
952   });
953   }
954   /** Delete nodes @private */
955   private deleteNode(d: COMPOSERNODES): void {
956     this.nodes.forEach((node: VNFD): void => {
957       if (node.id === d.id) {
958         if (d.type === 'cp') {
959           if (this.vnfdPackageDetails['ext-cpd'] !== undefined) {
960             let getRelatedVDUCPD: string; let getRelatedVDUID: string;
961             const posExtCPD: number = this.vnfdPackageDetails['ext-cpd'].findIndex((e: EXTCPD): boolean => {
962               if (e.id === d.name) {
963                 if (e['int-cpd'] !== undefined) {
964                   getRelatedVDUCPD = e['int-cpd'].cpd; getRelatedVDUID = e['int-cpd']['vdu-id'];
965                 }
966                 return true;
967               } else {
968                 return false;
969               }
970             });
971             if (posExtCPD !== -1) {
972               this.vnfdPackageDetails['ext-cpd'].splice(posExtCPD, 1);
973             }
974             if (getRelatedVDUCPD !== undefined && getRelatedVDUID !== undefined) {
975               this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
976                 if (vdu.id === getRelatedVDUID) {
977                   const posINTCPD: number = vdu['int-cpd'].findIndex((intCPD: VDUINTCPD): boolean => intCPD.id === getRelatedVDUCPD);
978                   if (posINTCPD !== -1) {
979                     vdu['int-cpd'].splice(posINTCPD, 1);
980                   }
981                 }
982               });
983             }
984           }
985         } else if (d.type === 'intcp') {
986           this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
987             const posINTCPD: number = vdu['int-cpd'].findIndex((intCPD: VDUINTCPD): boolean => intCPD.id === d.id);
988             if (posINTCPD !== -1) {
989               vdu['int-cpd'].splice(posINTCPD, 1);
990             }
991           });
992         } else if (d.type === 'intvl') {
993           const posINTVLD: number = this.vnfdPackageDetails['int-virtual-link-desc'].findIndex((intVLD: IVLD): boolean => intVLD.id === d.id);
994           if (posINTVLD !== -1) {
995             this.vnfdPackageDetails['int-virtual-link-desc'].splice(posINTVLD, 1);
996           }
997           if (this.vnfdPackageDetails.vdu !== undefined) {
998             this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU): void => {
999               if (vduDetails['int-cpd'] !== undefined) {
1000                 const newVDUintCPDArray: VDUINTCPD[] = vduDetails['int-cpd'].filter((item: VDUINTCPD): boolean => item['int-virtual-link-desc'] !== undefined ? item['int-virtual-link-desc'] !== d.id ? true : false : true);
1001                 vduDetails['int-cpd'] = newVDUintCPDArray;
1002               }
1003             });
1004           }
1005         } else if (d.type === 'vdu') {
1006           const getRelatedExtCPD: string[] = [];
1007           const posVDU: number = this.vnfdPackageDetails.vdu.findIndex((vduDetails: VDU): boolean => {
1008             if (vduDetails.id === d.id) {
1009               if (vduDetails['int-cpd'] !== undefined) {
1010                 vduDetails['int-cpd'].forEach((intCPDDetails: VDUINTCPD): void => {
1011                   if (intCPDDetails['int-virtual-link-desc'] === undefined) {
1012                     getRelatedExtCPD.push(intCPDDetails.id);
1013                   }
1014                 });
1015               }
1016               return true;
1017             } else {
1018               return false;
1019             }
1020           });
1021           if (posVDU !== -1) {
1022             this.vnfdPackageDetails.vdu.splice(posVDU, 1);
1023           }
1024           getRelatedExtCPD.forEach((CPDID: string, index: number): void => {
1025             this.vnfdPackageDetails['ext-cpd'].forEach((extCPD: EXTCPD): void => {
1026               if (extCPD['int-cpd'] !== undefined) {
1027                 if (extCPD['int-cpd'].cpd === CPDID) {
1028                   extCPD['int-cpd'] = {};
1029                 }
1030               }
1031             });
1032           });
1033         } else {
1034           this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
1035         }
1036         this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
1037       }
1038     });
1039   }
1040   /** Get confirmation before deleting the ink in Topology @private */
1041   private getDeleteLinkConfirmation(d: Tick): void {
1042     this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.YOUCANNOTDELETELINK'));
1043   }
1044   /** Selected nodes @private */
1045   // eslint-disable-next-line @typescript-eslint/no-explicit-any
1046   private selectedNode(nodeSeleced: any, d: COMPOSERNODES): void {
1047     const alreadyIsActive: boolean = nodeSeleced.select('#' + d.id).classed(this.activeNode);
1048     this.deselectAllNodes();
1049     nodeSeleced.select('#' + d.id).classed(this.activeNode, !alreadyIsActive);
1050     if (d.type === 'vdu' && !alreadyIsActive) {
1051       this.vnfdPackageDetails.vdu.forEach((res: VDU): void => {
1052         if (res.id === d.id) {
1053           this.showRightSideInfo = 'vduInfo';
1054           this.vduInfo = res;
1055           this.oldVDUID = res.id;
1056         }
1057       });
1058     } else if (d.type === 'cp' && !alreadyIsActive) {
1059       this.vnfdPackageDetails['ext-cpd'].forEach((cp: EXTCPD): void => {
1060         const getCPDID: string = cp['int-cpd'] !== undefined ? cp['int-cpd'].cpd : cp.id;
1061         if (getCPDID === d.id) {
1062           this.showRightSideInfo = 'cpInfo';
1063           this.cpInfo = cp;
1064           this.oldCPID = cp.id;
1065         }
1066       });
1067     } else if (d.type === 'intvl' && !alreadyIsActive) {
1068       this.vnfdPackageDetails['int-virtual-link-desc'].forEach((ivld: IVLD): void => {
1069         if (ivld.id === d.id) {
1070           this.showRightSideInfo = 'intvlInfo';
1071           this.intvlInfo = ivld;
1072           this.oldintVLID = ivld.id;
1073         }
1074       });
1075     } else if (d.type === 'intcp' && !alreadyIsActive) {
1076       this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
1077         vdu['int-cpd'].forEach((intcpd: VDUINTCPD): void => {
1078           if (intcpd.id === d.id) {
1079             if (intcpd['int-virtual-link-desc'] !== undefined) {
1080               intcpd['virtual-network-interface-requirement'].forEach((vnir: VNIR): void => {
1081                 this.intcpInfo = vnir;
1082                 this.showRightSideInfo = 'intcpInfo';
1083               });
1084             }
1085           }
1086         });
1087       });
1088     } else {
1089       this.showRightSideInfo = 'vnfdInfo';
1090     }
1091   }
1092   /** De-select all the selected nodes @private */
1093   private deselectAllNodes(): void {
1094     this.network.select('image').classed(this.activeNode, false);
1095     this.virutualDeploymentUnit.select('image').classed(this.activeNode, false);
1096     this.connectionPoint.select('image').classed(this.activeNode, false);
1097     this.intConnectionPoint.select('image').classed(this.activeNode, false);
1098   }
1099   /** Events handles when to drag using filter for the keys @private */
1100   private dragFilter(): boolean {
1101     return d3.event.ctrlKey && !d3.event.button;
1102   }
1103   /** Events handles when dragstarted @private */
1104   private dragstarted(d: COMPOSERNODES): void {
1105     d.fx = d.x;
1106     d.fy = d.y;
1107   }
1108   /** Events handles when dragged @private */
1109   private dragged(d: COMPOSERNODES): void {
1110     d.fx = d.x = d3.event.x;
1111     d.fy = d.y = d3.event.y;
1112   }
1113   /** Events handles when dragended @private */
1114   private dragended(d: COMPOSERNODES): void {
1115     if (this.forceSimulationActive) {
1116       d.fx = null;
1117       d.fy = null;
1118     } else {
1119       d.fx = d.x;
1120       d.fy = d.y;
1121       this.forceSimulationActive = false;
1122     }
1123   }
1124   /** Events handles when node double click   @private */
1125   private onNodedblClickToggleSidebar(): void {
1126     this.sideBarOpened = false;
1127   }
1128   /** Events handles when node single click   @private */
1129   private onNodeClickToggleSidebar(): void {
1130     this.sideBarOpened = true;
1131   }
1132 }