blob: 8981e26af512c98b65fe6d3484f961095b4b07c4 [file] [log] [blame]
kumaran.m3b4814a2020-05-01 19:48:54 +05301/*
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 Topology Component
20 */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +053021/* eslint-disable */
kumaran.m3b4814a2020-05-01 19:48:54 +053022import { Component, ElementRef, Injector, ViewChild, ViewEncapsulation } from '@angular/core';
23import { ActivatedRoute } from '@angular/router';
24import { Router } from '@angular/router';
25import { TranslateService } from '@ngx-translate/core';
26import { ERRORDATA } from 'CommonModel';
27import * as d3 from 'd3';
28import { environment } from 'environment';
29import * as HttpStatus from 'http-status-codes';
Barath Kumar R063a3f12020-12-29 16:35:09 +053030import { CCI, DF, VLC, VNFPROFILE } from 'NSDModel';
kumaran.m3b4814a2020-05-01 19:48:54 +053031import { COMPOSERNODES, CONNECTIONPOINT, NSD, NSDVLD, NSINFO, NSInstanceDetails, NSINSTANCENODES, VLINFO, VNFRINFO } from 'NSInstanceModel';
32import { GRAPHDETAILS, Tick, TickPath } from 'NSTopologyModel';
33import { RestService } from 'src/services/RestService';
34import { isNullOrUndefined } from 'util';
35
36/**
37 * Creating component
38 * @Component takes NSTopologyComponent.html as template url
39 */
40@Component({
41 selector: 'app-ns-topology',
42 templateUrl: './NSTopologyComponent.html',
43 styleUrls: ['./NSTopologyComponent.scss'],
44 encapsulation: ViewEncapsulation.None
45})
46/** Exporting a class @exports NSTopologyComponent */
47export class NSTopologyComponent {
48 /** Injector to invoke other services @public */
49 public injector: Injector;
50 /** View child contains graphContainer ref @public */
51 @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
52 /** Holds the basic information of NS @public */
53 public nsInfo: NSINFO;
54 /** Contains tranlsate instance @private */
55 public translateService: TranslateService;
56 /** Add the activeclass for the selected @public */
57 public activeClass: string = 'active';
58 /** Add the fixed class for the freeze @public */
59 public fixedClass: string = 'fixed';
60 /** Check the loading results @public */
61 public isLoadingResults: boolean = true;
62 /** Give the message for the loading @public */
63 public message: string = 'PLEASEWAIT';
64 /** Assign the forcesimulation active @public */
65 public forceSimulationActive: boolean = false;
66 /** Assign pinned class for the button when freezed @public */
67 public classApplied: boolean = false;
68 /** Contains sidebar open status @public */
69 public sideBarOpened: boolean = true;
70 /** Need to show the NS Details @public */
71 public isShowNSDetails: boolean = true;
72 /** Need to show the VL Details @public */
73 public isShowVLetails: boolean = false;
74 /** Need to show the VNFR Details @public */
75 public isShowVNFRDetails: boolean = false;
76 /** Show right side info of Virtual Link @public */
77 public virtualLink: VLINFO;
78 /** Show right side info of Virtual Link @public */
79 public vnfr: VNFRINFO;
80
81 /** Contains lastkeypressed instance @private */
82 private lastKeyDown: number = -1;
83 /** Instance of the rest service @private */
84 private restService: RestService;
85 /** Holds the instance of AuthService class of type AuthService @private */
86 private activatedRoute: ActivatedRoute;
87 /** Holds the NS Id @private */
88 private nsIdentifier: string;
89 /** Contains SVG attributes @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +053090 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +053091 private svg: any;
92 /** Contains forced node animations @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +053093 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +053094 private force: any;
95 /** Contains path information of the node */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +053096 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +053097 private path: any;
98 /** Contains node network @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +053099 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +0530100 private network: any;
101 /** Contains node square @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530102 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +0530103 private square: any;
104 /** Contains node circle @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530105 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +0530106 private circle: any;
107 /** Contains the NS information @private */
108 private nsData: NSInstanceDetails;
109 /** Contains NDS information of a descriptors */
110 private nsdData: NSD;
111 /** Contains node information @private */
112 private nodes: NSINSTANCENODES[] = [];
113 /** Contains links information @private */
114 private links: {}[] = [];
115 /** holds cp count/iteration @private */
116 private cpCount: number;
117 /** VNFD nodes @private */
118 private vnfdNodes: {}[] = [];
119 /** VLD nodes @private */
120 private vldNodes: {}[] = [];
121 /** Connection CP nodes @private */
122 private cpNodes: {}[] = [];
123 /** Set timeout @private */
124 private TIMEOUT: number = 2000;
125 /** Rendered nodes represent vnf @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530126 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +0530127 private gSquare: any;
128 /** Rendered nodes represent network @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530129 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +0530130 private gNetwork: any;
131 /** Rendered nodes represent network @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530132 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +0530133 private gCircle: any;
134 /** Service holds the router information @private */
135 private router: Router;
136
137 constructor(injector: Injector) {
138 this.injector = injector;
139 this.restService = this.injector.get(RestService);
140 this.activatedRoute = this.injector.get(ActivatedRoute);
141 this.translateService = this.injector.get(TranslateService);
142 this.router = this.injector.get(Router);
143 }
144
145 /**
146 * Lifecyle Hooks the trigger before component is instantiate @public
147 */
148 public ngOnInit(): void {
kumaran.m3b4814a2020-05-01 19:48:54 +0530149 this.nsIdentifier = this.activatedRoute.snapshot.paramMap.get('id');
150 this.generateData();
151 }
152 /** Event to freeze the animation @public */
153 public onFreeze(): void {
154 this.classApplied = !this.classApplied;
155 const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
156 d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
157 if (alreadyFixedIsActive) {
158 this.force.stop();
159 }
160 this.forceSimulationActive = alreadyFixedIsActive;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530161 this.nodes.forEach((d: COMPOSERNODES): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530162 d.fx = (alreadyFixedIsActive) ? null : d.x;
163 d.fy = (alreadyFixedIsActive) ? null : d.y;
164 });
165 if (alreadyFixedIsActive) {
166 this.force.restart();
167 }
168 }
169 /** Events handles when dragended @public */
170 public toggleSidebar(): void {
171 this.sideBarOpened = !this.sideBarOpened;
172 this.deselectAllNodes();
173 this.showRightSideInfo(true, false, false);
174 }
175 /** Get the default Configuration of containers @private */
176 private getGraphContainerAttr(): GRAPHDETAILS {
177 return {
178 width: 700,
179 height: 400,
180 nodeHeight: 50,
181 nodeWidth: 35,
182 textX: -35,
183 textY: 30,
184 radius: 5,
185 distance: 50,
186 strength: -500,
187 forcex: 2,
188 forcey: 2,
189 sourcePaddingYes: 17,
190 sourcePaddingNo: 12,
191 targetPaddingYes: 4,
192 targetPaddingNo: 3,
193 alphaTarget: 0.3,
194 imageX: -25,
195 imageY: -25,
196 shiftKeyCode: 17
197 };
198 }
199 /** Show the right-side information @private */
200 private showRightSideInfo(nsDetails: boolean, vlDetails: boolean, vnfrDeails: boolean): void {
201 this.isShowNSDetails = nsDetails;
202 this.isShowVLetails = vlDetails;
203 this.isShowVNFRDetails = vnfrDeails;
204 }
205 /** De-select all the selected nodes @private */
206 private deselectAllNodes(): void {
207 this.square.select('image').classed(this.activeClass, false);
208 this.network.select('image').classed(this.activeClass, false);
209 this.circle.select('image').classed(this.activeClass, false);
210 }
211 /** Prepare all the information for node creation @private */
212 private generateData(): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530213 this.restService.getResource(environment.NSINSTANCESCONTENT_URL + '/' + this.nsIdentifier)
214 .subscribe((nsData: NSInstanceDetails): void => {
215 this.nsData = nsData;
216 this.nsInfo = {
217 nsInstanceID: nsData._id,
218 nsName: nsData.name,
219 nsOperationalStatus: nsData['operational-status'],
220 nsConfigStatus: nsData['config-status'],
221 nsDetailedStatus: nsData['detailed-status'],
222 nsResourceOrchestrator: nsData['resource-orchestrator']
223 };
224 if (this.nsData['constituent-vnfr-ref'] !== undefined) {
225 this.generateVNFRCPNodes();
226 }
227 if (this.nsData.vld !== undefined) {
228 this.generateVLDNetworkNodes();
229 }
230 setTimeout((): void => {
231 this.pushAllNodes();
232 this.generateVNFDCP();
233 this.generateVLDCP();
234 this.isLoadingResults = false;
235 this.createNode(this.nodes, this.links);
236 }, this.TIMEOUT);
237 }, (error: ERRORDATA): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530238 this.isLoadingResults = false;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530239 if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530240 this.router.navigateByUrl('404', { skipLocationChange: true }).catch((): void => {
241 // Catch Navigation Error
242 });
Barath Kumar R063a3f12020-12-29 16:35:09 +0530243 } else {
244 this.restService.handleError(error, 'get');
245 }
246 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530247 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530248 /** Fetching all the VNFR Information @private */
249 private generateVNFRCPNodes(): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530250 this.nsData['constituent-vnfr-ref'].forEach((vnfdrID: string): void => {
251 this.restService.getResource(environment.VNFINSTANCES_URL + '/' + vnfdrID).subscribe((vndfrDetail: NSD): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530252 this.nodes.push({
253 id: vndfrDetail['vnfd-ref'] + ':' + vndfrDetail['member-vnf-index-ref'],
254 nodeTypeRef: 'vnfd',
255 cp: vndfrDetail['connection-point'],
256 vdur: vndfrDetail.vdur,
kumaran.m3b4814a2020-05-01 19:48:54 +0530257 nsID: vndfrDetail['nsr-id-ref'],
258 vnfdID: vndfrDetail['vnfd-id'],
259 vimID: vndfrDetail['vim-account-id'],
260 vndfrID: vndfrDetail.id,
261 ipAddress: vndfrDetail['ip-address'],
262 memberIndex: vndfrDetail['member-vnf-index-ref'],
263 vnfdRef: vndfrDetail['vnfd-ref'],
264 selectorId: 'nsInst-' + vndfrDetail.id
265 });
266 // Fetching all the connection point of VNF & Interface
Barath Kumar R063a3f12020-12-29 16:35:09 +0530267 vndfrDetail['connection-point'].forEach((cp: CONNECTIONPOINT): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530268 this.nodes.push({
269 id: cp.name + ':' + vndfrDetail['member-vnf-index-ref'],
270 vndfCPRef: vndfrDetail['vnfd-ref'] + ':' + vndfrDetail['member-vnf-index-ref'],
271 nodeTypeRef: 'cp',
272 name: cp.name
273 });
274 });
Barath Kumar R063a3f12020-12-29 16:35:09 +0530275 }, (error: ERRORDATA): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530276 this.restService.handleError(error, 'get');
277 });
278 });
279 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530280 /** Fetching all the VLD/Network Information @private */
281 private generateVLDNetworkNodes(): void {
282 this.nsdData = this.nsData.nsd;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530283 this.nsdData['virtual-link-desc'].forEach((ref: NSDVLD): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530284 this.nodes.push({
285 id: ref.id,
286 nodeTypeRef: 'vld',
Barath Kumar R063a3f12020-12-29 16:35:09 +0530287 name: ref.id,
kumaran.m3b4814a2020-05-01 19:48:54 +0530288 type: ref.type,
Barath Kumar R063a3f12020-12-29 16:35:09 +0530289 vnfdCP: this.nsdData.df,
kumaran.m3b4814a2020-05-01 19:48:54 +0530290 vimNetworkName: ref['vim-network-name'],
kumaran.m3b4814a2020-05-01 19:48:54 +0530291 selectorId: 'nsInst-' + ref.id
292 });
293 });
294 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530295 /** Pushing connection points of path/links nodes @private */
296 private pushAllNodes(): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530297 this.nodes.forEach((nodeList: NSINSTANCENODES): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530298 if (nodeList.nodeTypeRef === 'vnfd') {
299 this.vnfdNodes.push(nodeList);
300 } else if (nodeList.nodeTypeRef === 'vld') {
301 this.vldNodes.push(nodeList);
302 } else if (nodeList.nodeTypeRef === 'cp') {
303 this.cpNodes.push(nodeList);
304 }
305 });
306 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530307 /** Get CP position based on vndf @private */
308 private generateVNFDCP(): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530309 this.vnfdNodes.forEach((list: NSINSTANCENODES): void => {
310 const vndfPos: number = this.nodes.map((e: NSINSTANCENODES): string => { return e.id; }).indexOf(list.id);
kumaran.m3b4814a2020-05-01 19:48:54 +0530311 this.cpCount = 0;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530312 this.nodes.forEach((res: NSINSTANCENODES): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530313 if (res.nodeTypeRef === 'cp' && res.vndfCPRef === list.id) {
314 this.links.push({ source: this.nodes[vndfPos], target: this.nodes[this.cpCount] });
315 }
316 this.cpCount++;
317 });
318 });
319 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530320 /** Get CP position based on vld @private */
321 private generateVLDCP(): void {
322 let vldPos: number = 0;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530323 this.vldNodes.forEach((list: NSINSTANCENODES): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530324 if (!isNullOrUndefined(list.vnfdCP)) {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530325 list.vnfdCP.forEach((cpRef: DF): void => {
326 cpRef['vnf-profile'].forEach((vnfProfile: VNFPROFILE): void => {
327 vnfProfile['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => {
328 resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => {
329 this.cpCount = 0;
330 this.nodes.forEach((res: NSINSTANCENODES): void => {
331 if (res.nodeTypeRef === 'cp' &&
332 res.id === resultCCI['constituent-cpd-id'] + ':' + resultCCI['constituent-base-element-id']) {
333 this.links.push({ source: this.nodes[vldPos], target: this.nodes[this.cpCount] });
334 }
335 this.cpCount++;
336 });
337 });
338 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530339 });
340 });
341 vldPos++;
342 }
343 });
344 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530345 /** Node is created and render at D3 region @private */
346 private createNode(nodes: NSINSTANCENODES[], links: {}[]): void {
347 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
348 d3.selectAll('svg#graphContainer > *').remove();
Barath Kumar R063a3f12020-12-29 16:35:09 +0530349 d3.select(window).on('keydown', (): void => { this.keyDown(); });
350 d3.select(window).on('keyup', (): void => { this.keyUp(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530351 this.svg = d3.select('#graphContainer')
352 .attr('oncontextmenu', 'return false;')
353 .attr('width', graphContainerAttr.width)
354 .attr('height', graphContainerAttr.height);
355 this.force = d3.forceSimulation()
356 .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
Barath Kumar R063a3f12020-12-29 16:35:09 +0530357 .force('link', d3.forceLink().id((d: TickPath): string => d.id).distance(graphContainerAttr.distance))
kumaran.m3b4814a2020-05-01 19:48:54 +0530358 .force('center', d3.forceCenter(graphContainerAttr.width / graphContainerAttr.forcex,
359 graphContainerAttr.height / graphContainerAttr.forcey))
360 .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
361 .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
Barath Kumar R063a3f12020-12-29 16:35:09 +0530362 .on('tick', (): void => { this.tick(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530363 // handles to link and node element groups
364 this.path = this.svg.append('svg:g').selectAll('path');
365 this.network = this.svg.append('svg:g').selectAll('network');
366 this.square = this.svg.append('svg:g').selectAll('rect');
367 this.circle = this.svg.append('svg:g').selectAll('circle');
368 this.restart(nodes, links);
369 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530370 /** Update force layout (called automatically each iteration) @private */
371 private tick(): void {
372 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
373 // draw directed edges with proper padding from node centers
Barath Kumar R063a3f12020-12-29 16:35:09 +0530374 this.path.attr('class', 'link').attr('d', (d: Tick): string => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530375 const deltaX: number = d.target.x - d.source.x;
376 const deltaY: number = d.target.y - d.source.y;
377 const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
378 const normX: number = deltaX / dist;
379 const normY: number = deltaY / dist;
380 const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
381 const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
382 const sourceX: number = d.source.x + (sourcePadding * normX);
383 const sourceY: number = d.source.y + (sourcePadding * normY);
384 const targetX: number = d.target.x - (targetPadding * normX);
385 const targetY: number = d.target.y - (targetPadding * normY);
386 return `M${sourceX},${sourceY}L${targetX},${targetY}`;
387 });
Barath Kumar R063a3f12020-12-29 16:35:09 +0530388 this.network.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`);
389 this.square.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`);
390 this.circle.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`);
kumaran.m3b4814a2020-05-01 19:48:54 +0530391 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530392 /** Update graph (called when needed) @private */
393 private restart(nodes: NSINSTANCENODES[], links: {}[]): void {
394 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
395 this.path = this.path.data(links);
396 const vnfdNodes: {}[] = []; const vldNodes: {}[] = []; const cpNodes: {}[] = []; // NB: Nodes are known by id, not by index!
Barath Kumar R063a3f12020-12-29 16:35:09 +0530397 nodes.forEach((nodeList: NSINSTANCENODES): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530398 if (nodeList.nodeTypeRef === 'vnfd') { vnfdNodes.push(nodeList); }
399 else if (nodeList.nodeTypeRef === 'vld') { vldNodes.push(nodeList); }
400 else if (nodeList.nodeTypeRef === 'cp') { cpNodes.push(nodeList); }
401 });
Barath Kumar R063a3f12020-12-29 16:35:09 +0530402 this.square = this.square.data(vnfdNodes, (d: COMPOSERNODES): string => d.id);
403 this.network = this.network.data(vldNodes, (d: COMPOSERNODES): string => d.id);
404 this.circle = this.circle.data(cpNodes, (d: COMPOSERNODES): string => d.id);
kumaran.m3b4814a2020-05-01 19:48:54 +0530405 this.resetAndCreateNodes();
406 this.force.nodes(nodes).force('link').links(links); //Set the graph in motion
407 this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
408 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530409 /** Rest and create nodes @private */
410 private resetAndCreateNodes(): void {
411 this.path.exit().remove();
412 this.square.exit().remove();
413 this.network.exit().remove();
414 this.circle.exit().remove();
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530415 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +0530416 const gPath: any = this.path.enter().append('svg:path').attr('class', 'link');
417 this.getgSquare();
418 this.getgNetwork();
419 this.getgCircle();
420 this.square = this.gSquare.merge(this.square);
421 this.network = this.gNetwork.merge(this.network);
422 this.path = gPath.merge(this.path);
423 this.circle = this.gCircle.merge(this.circle);
424 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530425 /** Events handles when Shift Click to perform create cp @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530426 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +0530427 private singleClick(nodeSelected: any, d: COMPOSERNODES): void {
428 this.selectNodeExclusive(nodeSelected, d);
429 }
430 /** Selected nodes @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530431 // eslint-disable-next-line @typescript-eslint/no-explicit-any
kumaran.m3b4814a2020-05-01 19:48:54 +0530432 private selectNodeExclusive(nodeSelected: any, d: COMPOSERNODES): void {
433 const alreadyIsActive: boolean = nodeSelected.select('#' + d.selectorId).classed(this.activeClass);
434 this.deselectAllNodes();
435 nodeSelected.select('#' + d.selectorId).classed(this.activeClass, !alreadyIsActive);
436 if (d.nodeTypeRef === 'vld' && !alreadyIsActive) {
437 this.virtualLink = {
438 id: d.id,
439 name: d.name,
440 type: d.type,
441 shortName: d.shortName,
442 vimNetworkName: d.vimNetworkName
443 };
444 this.showRightSideInfo(false, true, false);
445 } else if (d.nodeTypeRef === 'vnfd' && !alreadyIsActive) {
446 this.vnfr = {
447 vimID: d.vimID,
448 _id: d.vndfrID,
449 ip: d.ipAddress,
450 nsrID: d.nsID,
451 id: d.selectorId,
452 vnfdRef: d.vnfdRef,
453 vnfdId: d.vnfdID,
454 memberIndex: d.memberIndex
455 };
456 this.showRightSideInfo(false, false, true);
457 } else {
458 this.showRightSideInfo(true, false, false);
459 }
460 }
461 /** Setting all the square/vnf attributes of nodes @private */
462 private getgSquare(): void {
463 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
464 this.gSquare = this.square.enter().append('svg:g');
465 this.gSquare.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
466 this.gSquare.append('svg:image')
467 .style('opacity', 1)
468 .attr('x', graphContainerAttr.imageX)
469 .attr('y', graphContainerAttr.imageY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530470 .call(this.onDragDrop())
471 .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; })
kumaran.m3b4814a2020-05-01 19:48:54 +0530472 .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
473 .attr('xlink:href', 'assets/images/VNFD.svg')
Barath Kumar R063a3f12020-12-29 16:35:09 +0530474 .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.gSquare, d); this.onNodeClickToggleSidebar(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530475 this.gSquare.append('svg:text')
476 .attr('class', 'node_text')
477 .attr('y', graphContainerAttr.textY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530478 .text((d: COMPOSERNODES): string => d.id);
kumaran.m3b4814a2020-05-01 19:48:54 +0530479 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530480 /** Settings all the network attributes of nodes @private */
481 private getgNetwork(): void {
482 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
483 this.gNetwork = this.network.enter().append('svg:g');
484 this.gNetwork.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
485 this.gNetwork.append('svg:image')
486 .style('opacity', 1)
487 .attr('x', graphContainerAttr.imageX)
488 .attr('y', graphContainerAttr.imageY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530489 .call(this.onDragDrop())
490 .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; })
kumaran.m3b4814a2020-05-01 19:48:54 +0530491 .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
492 .attr('xlink:href', 'assets/images/VL.svg')
Barath Kumar R063a3f12020-12-29 16:35:09 +0530493 .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.gNetwork, d); this.onNodeClickToggleSidebar(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530494 this.gNetwork.append('svg:text')
495 .attr('class', 'node_text')
496 .attr('y', graphContainerAttr.textY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530497 .text((d: COMPOSERNODES): string => d.name);
kumaran.m3b4814a2020-05-01 19:48:54 +0530498 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530499 /** Settings all the connection point attributes of nodes @private */
500 private getgCircle(): void {
501 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
502 this.gCircle = this.circle.enter().append('svg:g');
503 this.gCircle.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
504 this.gCircle.append('svg:image')
505 .style('opacity', 1)
506 .attr('x', graphContainerAttr.imageX)
507 .attr('y', graphContainerAttr.imageY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530508 .call(this.onDragDrop())
kumaran.m3b4814a2020-05-01 19:48:54 +0530509 .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
510 .attr('xlink:href', 'assets/images/CP.svg');
511 this.gCircle.append('svg:text')
512 .attr('class', 'node_text')
513 .attr('y', graphContainerAttr.textY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530514 .text((d: COMPOSERNODES): string => d.name);
kumaran.m3b4814a2020-05-01 19:48:54 +0530515 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530516 /** drag event @private */
SANDHYA.JS0a34dfa2023-04-25 23:59:41 +0530517 // eslint-disable-next-line @typescript-eslint/no-explicit-any
Barath Kumar R063a3f12020-12-29 16:35:09 +0530518 private onDragDrop(): any {
519 return d3.drag().filter(this.dragFilter)
520 .on('start', this.dragstarted)
521 .on('drag', this.dragged)
522 .on('end', this.dragended);
523 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530524 /** Key press event @private */
525 private keyDown(): void {
526 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
527 if (this.lastKeyDown !== -1) { return; }
528 this.lastKeyDown = d3.event.keyCode;
529 if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
530 this.gSquare.call(d3.drag()
531 .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended)
532 );
533 this.gNetwork.call(d3.drag()
534 .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended)
535 );
536 this.gCircle.call(d3.drag()
537 .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended)
538 );
539 this.svg.classed('ctrl', true);
540 }
541 }
542 /** Key realse event @private */
543 private keyUp(): void {
544 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
545 this.lastKeyDown = -1;
546 if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
547 this.gSquare.on('.drag', null);
548 this.gNetwork.on('.drag', null);
549 this.gCircle.on('.drag', null);
550 this.svg.classed('ctrl', false);
551 }
552 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530553 /** Events handles when to drag using filter for the keys @private */
554 private dragFilter(): boolean {
555 return d3.event.ctrlKey && !d3.event.button;
556 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530557 /** Events handles when dragstarted @private */
558 private dragstarted(d: COMPOSERNODES): void {
559 d.fx = d.x;
560 d.fy = d.y;
561 }
562 /** Events handles when dragged @private */
563 private dragged(d: COMPOSERNODES): void {
564 d.fx = d.x = d3.event.x;
565 d.fy = d.y = d3.event.y;
566 }
567 /** Events handles when dragended @private */
568 private dragended(d: COMPOSERNODES): void {
569 if (this.forceSimulationActive) {
570 d.fx = null;
571 d.fy = null;
572 } else {
573 d.fx = d.x;
574 d.fy = d.y;
575 this.forceSimulationActive = false;
576 }
577 }
578 /** Events handles when node single click @private */
579 private onNodeClickToggleSidebar(): void {
580 this.sideBarOpened = true;
581 }
582}