Initial Commit - NG UI
* Roboto and font-awesome fonts are added in package.json
* Replace Nginx alpine varient to stable
* Devops files are added
* Docker file aligned as per community reviews
* Enhancement - NS primitive, Azure inclusion and domain name
* RWD changes
Change-Id: If543efbf127964cbd8f4be4c5a67260c91407fd9
Signed-off-by: kumaran.m <kumaran.m@tataelxsi.co.in>
diff --git a/src/app/packages/ns-packages/vnf-composer/VNFComposerComponent.ts b/src/app/packages/ns-packages/vnf-composer/VNFComposerComponent.ts
new file mode 100644
index 0000000..21aad71
--- /dev/null
+++ b/src/app/packages/ns-packages/vnf-composer/VNFComposerComponent.ts
@@ -0,0 +1,1020 @@
+/*
+ Copyright 2020 TATA ELXSI
+
+ Licensed under the Apache License, Version 2.0 (the 'License');
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file VNFComposerComponent
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, ViewChild, ViewEncapsulation } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, GETAPIURLHEADER, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { ConfirmationTopologyComponent } from 'ConfirmationTopology';
+import * as d3 from 'd3';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import * as HttpStatus from 'http-status-codes';
+import * as jsyaml from 'js-yaml';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+import {
+ COMPOSERNODES, CONNECTIONPOINT, GRAPHDETAILS, InternalVLD, Tick, TickPath,
+ VDU, VDUInternalConnectionPoint, VLDInternalConnectionPoint, VNFDInterface, VNFDNODE
+} from 'VNFDModel';
+
+/**
+ * Creating component
+ * @Component takes VNFComposerComponent.html as template url
+ */
+@Component({
+ templateUrl: './VNFComposerComponent.html',
+ styleUrls: ['./VNFComposerComponent.scss'],
+ encapsulation: ViewEncapsulation.None
+})
+/** Exporting a class @exports VNFComposerComponent */
+export class VNFComposerComponent {
+ /** To inject services @public */
+ public injector: Injector;
+ /** View child contains graphContainer ref @public */
+ @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
+ /** dataService to pass the data from one component to another @public */
+ public dataService: DataService;
+ /** random number count @public */
+ public randomNumberLength: number;
+ /** Contains the vnfd information @public */
+ public vnfList: string[] = [];
+ /** Contains node type @public */
+ public nodeTypeRef: string;
+ /** Contains VNFD Information @public */
+ public vnfdInfo: VNFDNODE = { shortName: '', description: '', version: '', id: '', name: '' };
+ /** Contains right panel box information @public */
+ public showRightSideInfo: string = '';
+ /** Add the fixed class for the freeze @public */
+ public fixedClass: string = 'fixed';
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+ /** Assign the forcesimulation active @public */
+ public forceSimulationActive: boolean = false;
+ /** Assign pinned class for the button when freezed @public */
+ public classApplied: boolean = false;
+ /** Contains sidebar open status @public */
+ public sideBarOpened: boolean = false;
+
+ /** Contains SVG attributes @private */
+ // tslint:disable-next-line:no-any
+ private svg: any;
+ /** Contains forced node animations @private */
+ // tslint:disable-next-line:no-any
+ private force: any;
+ /** Contains the Drag line */
+ // tslint:disable-next-line: no-any
+ private dragLine: any;
+ /** Contains id of the node @private */
+ private identifier: string;
+ /** Contains path information of the node */
+ // tslint:disable-next-line:no-any
+ private path: any;
+ /** Contains node network @private */
+ // tslint:disable-next-line:no-any
+ private network: any;
+ /** Contains node network @private */
+ // tslint:disable-next-line:no-any
+ private virutualDeploymentUnit: any;
+ /** Contains node connectionPoint @private */
+ // tslint:disable-next-line:no-any
+ private connectionPoint: any;
+ /** Contains node intConnectionPoint @private */
+ // tslint:disable-next-line:no-any
+ private intConnectionPoint: any;
+ /** Contains the node information @private */
+ private nodes: VNFDNODE[] = [];
+ /** Contains the link information of nodes @private */
+ private links: {}[] = [];
+ /** Instance of the rest service @private */
+ private restService: RestService;
+ /** Service holds the router information @private */
+ private router: Router;
+ /** Service contails all the shared service information @private */
+ private sharedService: SharedService;
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private activatedRoute: ActivatedRoute;
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+ /** Rendered nodes represent network @private */
+ // tslint:disable-next-line:no-any
+ private gNetwork: any;
+ /** Rendered nodes represent VDU @private */
+ // tslint:disable-next-line:no-any
+ private gVirutualDeploymentUnit: any;
+ /** Rendered nodes represent connection point @private */
+ // tslint:disable-next-line:no-any
+ private gConnectionPoint: any;
+ /** Rendered nodes represent internal connection point @private */
+ // tslint:disable-next-line:no-any
+ private gIntConnectionPoint: any;
+ /** Contains all the information about VNF Details @private */
+ private vnfdPackageDetails: VNFDNODE;
+ /** Conatins mousedown action @private */
+ private mousedownNode: COMPOSERNODES = null;
+ /** Conatins mouseup action @private */
+ private mouseupNode: COMPOSERNODES = null;
+ /** Conatins current Selection node action @private */
+ private currentSelectedNode: COMPOSERNODES = null;
+ /** Add the activeNode for the selected @private */
+ private activeNode: string = 'active';
+ /** Contains lastkeypressed instance @private */
+ private lastKeyDown: number = -1;
+ /** Contains VDU Information @private */
+ private vduInfo: VDU;
+ /** Contains Internal VL Information @private */
+ private intvlInfo: InternalVLD;
+ /** Contains Connection Point Information @private */
+ private cpInfo: CONNECTIONPOINT;
+ /** Contains Internal Connection Point Information @private */
+ private intcpInfo: VLDInternalConnectionPoint;
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.router = this.injector.get(Router);
+ this.activatedRoute = this.injector.get(ActivatedRoute);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.identifier = this.activatedRoute.snapshot.paramMap.get('id');
+ this.generateData();
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/zip',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ }
+
+ /** Prepare information for node creation of VNFD @public */
+ public generateData(): void {
+ this.nodes = []; this.links = []; this.vnfdPackageDetails = null;
+ this.showRightSideInfo = 'vnfdInfo';
+ const httpOptions: GETAPIURLHEADER = {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/zip',
+ Accept: 'text/plain',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ }),
+ responseType: 'text'
+ };
+ this.restService.getResource(environment.VNFPACKAGES_URL + '/' + this.identifier + '/vnfd', httpOptions)
+ .subscribe((vnfdPackageDetails: VNFDNODE) => {
+ try {
+ const getJson: string = jsyaml.load(vnfdPackageDetails.toString(), { json: true });
+ if (getJson.hasOwnProperty('vnfd-catalog')) {
+ this.vnfdPackageDetails = getJson['vnfd-catalog'].vnfd[0];
+ } else if (getJson.hasOwnProperty('vnfd:vnfd-catalog')) {
+ this.vnfdPackageDetails = getJson['vnfd:vnfd-catalog'].vnfd[0];
+ } else if (getJson.hasOwnProperty('vnfd')) {
+ // tslint:disable-next-line: no-string-literal
+ this.vnfdPackageDetails = getJson['vnfd'][0];
+ }
+ this.generateCPPoint(this.vnfdPackageDetails);
+ this.generateVDU(this.vnfdPackageDetails);
+ this.generateInternalVLD(this.vnfdPackageDetails);
+ this.generateInternalCP(this.vnfdPackageDetails);
+ this.generateIntVLCPLinks(this.vnfdPackageDetails);
+ this.generateVDUCPLinks(this.vnfdPackageDetails);
+ this.createNode(this.nodes);
+ this.vnfdInfo.shortName = this.vnfdPackageDetails['short-name'];
+ this.vnfdInfo.description = this.vnfdPackageDetails.description;
+ this.vnfdInfo.version = this.vnfdPackageDetails.version;
+ this.vnfdInfo.id = this.vnfdPackageDetails.id;
+ this.vnfdInfo.name = this.vnfdPackageDetails.name;
+ } catch (e) {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ error.error = typeof error.error === 'string' ? jsyaml.load(error.error) : error.error;
+ if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
+ this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
+ } else {
+ this.restService.handleError(error, 'get');
+ }
+ this.isLoadingResults = false;
+ this.showRightSideInfo = '';
+ });
+ }
+ /** Events handles at drag on D3 region @public */
+ // tslint:disable-next-line:no-any
+ public drag(ev: any): void {
+ ev.dataTransfer.setData('text', ev.target.id);
+ }
+ /** Events handles drop at D3 region @public */
+ public drop(ev: DragEvent): void {
+ ev.preventDefault();
+ this.nodeTypeRef = ev.dataTransfer.getData('text');
+ if (this.nodeTypeRef === 'vdu') {
+ this.svg.selectAll('*').remove();
+ this.vduDropCompose();
+ } else if (this.nodeTypeRef === 'cp') {
+ this.svg.selectAll('*').remove();
+ this.cpDropCompose();
+ } else if (this.nodeTypeRef === 'intvl') {
+ this.svg.selectAll('*').remove();
+ this.intvlDropCompose();
+ }
+ }
+ /** Events handles allow drop on D3 region @public */
+ public allowDrop(ev: DragEvent): void {
+ ev.preventDefault();
+ }
+ /** Generate and list CP points @public */
+ public generateCPPoint(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails['connection-point'] !== undefined) {
+ vnfdPackageDetails['connection-point'].forEach((cp: CONNECTIONPOINT) => {
+ this.nodes.push({ id: cp.name, nodeTypeRef: 'cp', name: cp.name, type: cp.type });
+ });
+ }
+ }
+ /** Generate and list VDU @public */
+ public generateVDU(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails.vdu !== undefined) {
+ vnfdPackageDetails.vdu.forEach((vdu: VDU) => {
+ this.nodes.push({
+ id: vdu.name, nodeTypeRef: 'vdu', 'cloud-init-file': vdu['cloud-init-file'], count: vdu.count, description: vdu.description,
+ vduID: vdu.id, name: vdu.name, interface: vdu.interface, 'vm-flavor': vdu['vm-flavor']
+ });
+ });
+ }
+ }
+ /** Generate and list Internal VLD @public */
+ public generateInternalVLD(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails['internal-vld'] !== undefined) {
+ vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
+ this.nodes.push({
+ id: internalVLD.name, nodeTypeRef: 'intvl', intVLID: internalVLD.id,
+ 'internal-connection-point': internalVLD['internal-connection-point'],
+ 'ip-profile-ref': internalVLD['ip-profile-ref'], name: internalVLD.name, 'short-name': internalVLD['short-name'],
+ type: internalVLD.type
+ });
+ });
+ }
+ }
+ /** Generate and list Internal CP @public */
+ public generateInternalCP(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails.vdu !== undefined) {
+ vnfdPackageDetails.vdu.forEach((intCP: VDUInternalConnectionPoint) => {
+ if (intCP['internal-connection-point'] !== undefined) {
+ intCP['internal-connection-point'].forEach((internalCP: VDUInternalConnectionPoint) => {
+ this.nodes.push({
+ id: internalCP.name, nodeTypeRef: 'intcp', name: internalCP.name,
+ 'short-name': internalCP['short-name'], type: internalCP.type
+ });
+ });
+ }
+ });
+ }
+ }
+ /** Generate VDU External and Internal CP Links @public */
+ public generateVDUCPLinks(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails.vdu !== undefined) {
+ vnfdPackageDetails.vdu.forEach((vdu: VDU) => {
+ const vduLink: string = vdu.name;
+ if (vdu.interface !== undefined) {
+ vdu.interface.forEach((interfaceDetails: VNFDInterface) => {
+ if (interfaceDetails['external-connection-point-ref'] !== undefined) {
+ this.links.push({ source: vduLink, target: interfaceDetails['external-connection-point-ref'] });
+ }
+ if (interfaceDetails['internal-connection-point-ref'] !== undefined) {
+ this.links.push({ source: vduLink, target: interfaceDetails['internal-connection-point-ref'] });
+ }
+ });
+ }
+ });
+ }
+ }
+ /** Generate Network/VLD/Internal VirtualLink, CP Links @public */
+ public generateIntVLCPLinks(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails['internal-vld'] !== undefined) {
+ vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
+ const vldName: string = internalVLD.name;
+ if (internalVLD['internal-connection-point'] !== undefined) {
+ internalVLD['internal-connection-point'].forEach((intCP: VLDInternalConnectionPoint) => {
+ this.links.push({ source: vldName, target: intCP['id-ref'] });
+ });
+ }
+ });
+ }
+ }
+ /** VNFD details can be saved on users inputs @public */
+ public saveVNFD(): void {
+ this.vnfdPackageDetails['short-name'] = this.vnfdInfo.shortName;
+ this.vnfdPackageDetails.description = this.vnfdInfo.description;
+ this.vnfdPackageDetails.version = this.vnfdInfo.version;
+ this.vnfdPackageDetails.id = this.vnfdInfo.id;
+ this.vnfdPackageDetails.name = this.vnfdInfo.name;
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ delete this.vnfdPackageDetails.shortName;
+ }
+ /** VDU details can be saved on users inputs @public */
+ public saveVDU(vduID: string): void {
+ this.vnfdPackageDetails.vdu.forEach((ref: VDU) => {
+ if (ref.id === vduID) {
+ ref.count = this.vduInfo.count;
+ ref.description = this.vduInfo.description;
+ ref.image = this.vduInfo.image;
+ ref.id = this.vduInfo.id;
+ ref.name = this.vduInfo.name;
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** IntVL details can be saved on users inputs @public */
+ public saveIntVL(intVLID: string): void {
+ this.vnfdPackageDetails['internal-vld'].forEach((ref: InternalVLD) => {
+ if (ref.id === intVLID) {
+ ref['short-name'] = this.intvlInfo.shortName;
+ ref.name = this.intvlInfo.name;
+ ref.type = this.intvlInfo.type;
+ ref['ip-profile-ref'] = !isNullOrUndefined(this.intvlInfo.ipProfileRef) ? this.intvlInfo.ipProfileRef : '';
+ ref.id = this.intvlInfo.id;
+ delete ref.shortName;
+ delete ref.ipProfileRef;
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** IntVL details can be saved on users inputs @public */
+ public saveCP(cpName: string): void {
+ this.vnfdPackageDetails['connection-point'].forEach((ref: CONNECTIONPOINT) => {
+ if (ref.name === cpName) {
+ if (!isNullOrUndefined(this.cpInfo.type)) {
+ ref.type = this.cpInfo.type;
+ }
+ ref.name = this.cpInfo.name;
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** Edit topology @public */
+ public onEdit(): void {
+ this.router.navigate(['/packages/vnf/edit/', this.identifier]).catch();
+ }
+ /** Show Info @public */
+ public showInfo(): void {
+ const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
+ modalRef.componentInstance.topologyType = 'Info';
+ modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.INFO');
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ // empty
+ }
+ }).catch();
+ }
+ /** Event to freeze the animation @public */
+ public onFreeze(): void {
+ this.classApplied = !this.classApplied;
+ const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
+ d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
+ if (alreadyFixedIsActive) {
+ this.force.stop();
+ }
+ this.forceSimulationActive = alreadyFixedIsActive;
+ this.nodes.forEach((d: COMPOSERNODES) => {
+ d.fx = (alreadyFixedIsActive) ? null : d.x;
+ d.fy = (alreadyFixedIsActive) ? null : d.y;
+ });
+ if (alreadyFixedIsActive) {
+ this.force.restart();
+ }
+ }
+ /** Events handles when dragended @public */
+ public toggleSidebar(): void {
+ this.sideBarOpened = !this.sideBarOpened;
+ this.deselectAllNodes();
+ this.showRightSideInfo = 'vnfdInfo';
+ }
+ /** Get the default Configuration of containers @private */
+ private getGraphContainerAttr(): GRAPHDETAILS {
+ return {
+ width: 700,
+ height: 400,
+ nodeHeight: 50,
+ nodeWidth: 35,
+ textX: -35,
+ textY: 30,
+ radius: 5,
+ distance: 50,
+ strength: -500,
+ forcex: 2,
+ forcey: 2,
+ sourcePaddingYes: 17,
+ sourcePaddingNo: 12,
+ targetPaddingYes: 4,
+ targetPaddingNo: 3,
+ alphaTarget: 0.3,
+ imageX: -25,
+ imageY: -25,
+ shiftKeyCode: 17
+ };
+ }
+ /** Node is created and render at D3 region @private */
+ private createNode(nodes: VNFDNODE[]): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ d3.selectAll('svg#graphContainer > *').remove();
+ d3.select(window).on('keydown', () => { this.keyDown(); });
+ d3.select(window).on('keyup', () => { this.keyUp(); });
+ this.svg = d3.select('#graphContainer').attr('oncontextmenu', 'return false;').attr('width', graphContainerAttr.width)
+ .attr('height', graphContainerAttr.height).on('mousemove', () => { this.mousemove(); });
+ this.force = d3.forceSimulation()
+ .force('link', d3.forceLink().id((d: TickPath) => d.id).distance(graphContainerAttr.distance))
+ .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
+ .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
+ .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
+ .on('tick', () => { this.tick(); });
+ this.path = this.svg.append('svg:g').selectAll('path');
+ this.dragLine = this.svg.append('svg:path').attr('class', 'link dragline hidden').attr('d', 'M0,0L0,0');
+ this.network = this.svg.append('svg:g').selectAll('network');
+ this.virutualDeploymentUnit = this.svg.append('svg:g').selectAll('virutualDeploymentUnit');
+ this.connectionPoint = this.svg.append('svg:g').selectAll('connectionPoint');
+ this.intConnectionPoint = this.svg.append('svg:g').selectAll('intConnectionPoint');
+ this.restart(nodes);
+ }
+ /** Update force layout (called automatically each iteration) @private */
+ private tick(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.path.attr('d', (d: Tick) => {
+ const deltaX: number = d.target.x - d.source.x; const deltaY: number = d.target.y - d.source.y;
+ const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+ const normX: number = deltaX / dist; const normY: number = deltaY / dist;
+ const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
+ const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
+ const sourceX: number = d.source.x + (sourcePadding * normX); const sourceY: number = d.source.y + (sourcePadding * normY);
+ const targetX: number = d.target.x - (targetPadding * normX); const targetY: number = d.target.y - (targetPadding * normY);
+ return `M${sourceX},${sourceY}L${targetX},${targetY}`;
+ }).on('dblclick', (d: Tick) => { this.getDeleteLinkConfirmation(d); });
+ this.network.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
+ this.virutualDeploymentUnit.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
+ this.connectionPoint.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
+ this.intConnectionPoint.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
+ }
+ /** Update graph (called when needed) @private */
+ private restart(nodes: VNFDNODE[]): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.path = this.path.data(this.links);
+ const cpNodes: {}[] = []; const vduNodes: {}[] = []; const vlNodes: {}[] = []; const intcpNodes: {}[] = []; //Nodes are known by id
+ nodes.forEach((nodeList: VNFDNODE) => {
+ if (nodeList.nodeTypeRef === 'cp') { cpNodes.push(nodeList); }
+ else if (nodeList.nodeTypeRef === 'vdu') { vduNodes.push(nodeList); }
+ else if (nodeList.nodeTypeRef === 'intvl') { vlNodes.push(nodeList); }
+ else if (nodeList.nodeTypeRef === 'intcp') { intcpNodes.push(nodeList); }
+ });
+ this.network = this.network.data(vlNodes, (d: { id: number }) => d.id);
+ this.virutualDeploymentUnit = this.virutualDeploymentUnit.data(vduNodes, (d: { id: number }) => d.id);
+ this.connectionPoint = this.connectionPoint.data(cpNodes, (d: { id: number }) => d.id);
+ this.intConnectionPoint = this.intConnectionPoint.data(intcpNodes, (d: { id: number }) => d.id);
+ this.resetAndCreateNodes();
+ this.force.nodes(nodes).force('link').links(this.links); //Set the graph in motion
+ this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
+ }
+ /** Rest and create nodes @private */
+ private resetAndCreateNodes(): void {
+ this.path.exit().remove();
+ this.network.exit().remove();
+ this.virutualDeploymentUnit.exit().remove();
+ this.connectionPoint.exit().remove();
+ this.intConnectionPoint.exit().remove();
+ this.getPathNodes();
+ this.getgNetwork();
+ this.getgVirutualDeploymentUnit();
+ this.getgConnectionPoint();
+ this.getgIntConnectionPoint();
+ this.network = this.gNetwork.merge(this.network);
+ this.virutualDeploymentUnit = this.gVirutualDeploymentUnit.merge(this.virutualDeploymentUnit);
+ this.connectionPoint = this.gConnectionPoint.merge(this.connectionPoint);
+ this.intConnectionPoint = this.gIntConnectionPoint.merge(this.intConnectionPoint);
+ this.path.merge(this.path);
+ }
+ /** Setting the Path @private */
+ private getPathNodes(): void {
+ this.path = this.path.enter().append('svg:path').attr('class', 'link');
+ }
+ /** Settings all the network attributes of nodes @private */
+ private getgNetwork(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gNetwork = this.network.enter().append('svg:g');
+ this.gNetwork.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gNetwork.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: VNFDNODE) => { return d.id; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/INTVL.svg')
+ .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
+ .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
+ .on('click', (d: VNFDNODE) => { this.singleClick(this.network, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gNetwork.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: { id: number }) => d.id);
+ }
+ /** Settings all the connection point attributes of nodes @private */
+ private getgVirutualDeploymentUnit(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gVirutualDeploymentUnit = this.virutualDeploymentUnit.enter().append('svg:g');
+ this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gVirutualDeploymentUnit.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: VNFDNODE) => { return d.id; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/VDU.svg')
+ .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
+ .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
+ .on('click', (d: VNFDNODE) => { this.singleClick(this.virutualDeploymentUnit, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gVirutualDeploymentUnit.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: { id: string }) => d.id);
+ }
+ /** Settings all the connection point attributes of nodes @private */
+ private getgConnectionPoint(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gConnectionPoint = this.connectionPoint.enter().append('svg:g');
+ this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gConnectionPoint.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: VNFDNODE) => { return d.id; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/CP-VNF.svg')
+ .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
+ .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
+ .on('click', (d: VNFDNODE) => { this.singleClick(this.connectionPoint, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gConnectionPoint.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: { id: string }) => d.id);
+ }
+ /** Settings all the internal connection point attributes of nodes @private */
+ private getgIntConnectionPoint(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gIntConnectionPoint = this.intConnectionPoint.enter().append('svg:g');
+ this.gIntConnectionPoint.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gIntConnectionPoint.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: VNFDNODE) => { return d.id; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/INTCP.svg')
+ .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
+ .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
+ .on('click', (d: VNFDNODE) => { this.singleClick(this.intConnectionPoint, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gIntConnectionPoint.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: { id: string }) => d.id);
+ }
+ /** Drop VDU Composer Data @private */
+ private vduDropCompose(): void {
+ const randomID: string = this.sharedService.randomString();
+ const vduNode: VNFDNODE[] = [{
+ nodeTypeRef: 'vdu', id: 'vdu_' + randomID, count: 1, description: '', name: 'vdu_' + randomID, image: 'ubuntu',
+ interface: [], 'internal-connection-point': [], 'monitoring-param': [], 'vm-flavor': {}
+ }];
+ const nodeCopy: VNFDNODE[] = this.nodes;
+ Array.prototype.push.apply(vduNode, nodeCopy);
+ this.nodes = vduNode;
+ if (this.vnfdPackageDetails.vdu === undefined) { this.vnfdPackageDetails.vdu = []; }
+ this.vnfdPackageDetails.vdu.push({
+ id: 'vdu_' + randomID, count: 1, description: '', name: 'vdu_' + randomID, image: 'ubuntu',
+ interface: [], 'internal-connection-point': [], 'monitoring-param': [], 'vm-flavor': {}
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** Drop CP Composer Data @private */
+ private cpDropCompose(): void {
+ const randomID: string = this.sharedService.randomString();
+ const cpNode: VNFDNODE[] = [{ nodeTypeRef: 'cp', id: 'cp_' + randomID, name: 'cp_' + randomID }];
+ const nodeCopy: VNFDNODE[] = this.nodes;
+ Array.prototype.push.apply(cpNode, nodeCopy);
+ this.nodes = cpNode;
+ if (this.vnfdPackageDetails['connection-point'] === undefined) {
+ this.vnfdPackageDetails['connection-point'] = [];
+ }
+ this.vnfdPackageDetails['connection-point'].push({
+ id: 'cp_' + randomID, name: 'cp_' + randomID, type: 'VPORT'
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** Drop IntVL Composer Data @private */
+ private intvlDropCompose(): void {
+ const randomID: string = this.sharedService.randomString();
+ const intvlNode: VNFDNODE[] = [{
+ nodeTypeRef: 'intvl', id: 'vnf_vl_' + randomID, name: 'vnf_vl_' + randomID, 'short-name': 'vnf_vl_' + randomID, 'ip-profile-ref': '',
+ type: 'ELAN'
+ }];
+ const nodeCopy: VNFDNODE[] = this.nodes;
+ Array.prototype.push.apply(intvlNode, nodeCopy);
+ this.nodes = intvlNode;
+ if (this.vnfdPackageDetails['internal-vld'] === undefined) { this.vnfdPackageDetails['internal-vld'] = []; }
+ this.vnfdPackageDetails['internal-vld'].push({
+ id: 'vnf_vl_' + randomID, name: 'vnf_vl_' + randomID, 'short-name': 'vnf_vl_' + randomID,
+ 'ip-profile-ref': '', type: 'ELAN', 'internal-connection-point': []
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** Add the Add Nodes Data @private */
+ private addNodes(apiURL: string, identifier: string, data: VNFDNODE): void {
+ this.isLoadingResults = true;
+ const apiURLHeader: APIURLHEADER = {
+ url: apiURL + '/' + identifier + '/package_content',
+ httpOptions: { headers: this.headers }
+ };
+ const vnfData: {} = {};
+ vnfData['vnfd:vnfd-catalog'] = {};
+ vnfData['vnfd:vnfd-catalog'].vnfd = [];
+ vnfData['vnfd:vnfd-catalog'].vnfd.push(data);
+ const descriptorInfo: string = jsyaml.dump(vnfData, { sortKeys: true });
+ this.sharedService.targzFile({ packageType: 'vnfd', id: this.identifier, descriptor: descriptorInfo })
+ .then((content: ArrayBuffer): void => {
+ this.restService.putResource(apiURLHeader, content).subscribe((res: {}) => {
+ this.generateData();
+ this.notifierService.notify('success', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.UPDATEDSUCCESSFULLY'));
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.generateData();
+ this.restService.handleError(error, 'put');
+ this.isLoadingResults = false;
+ });
+ }).catch((): void => {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ this.isLoadingResults = false;
+ });
+ }
+ /** Events handles when mousedown click it will capture the selected node data @private */
+ private mouseDown(d: VNFDNODE): void {
+ event.preventDefault();
+ if (d3.event.ctrlKey) { return; }
+ if (d3.event.shiftKey) {
+ this.mousedownNode = d;
+ this.currentSelectedNode = (this.mousedownNode === this.currentSelectedNode) ? null : this.mousedownNode;
+ this.dragLine.classed('hidden', false)
+ .attr('d', `M${this.mousedownNode.x},${this.mousedownNode.y}L${this.mousedownNode.x},${this.mousedownNode.y}`);
+ }
+ }
+ /** Event handles when mouseup event occures @private */
+ private mouseUp(d: VNFDNODE): void {
+ if (!this.mousedownNode) { return; }
+ this.dragLine.classed('hidden', true);
+ this.mouseupNode = d;
+ if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'intcp') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDINTCP'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'vdu') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDVDU'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'vdu') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVDU'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'intvl') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDVNFVL'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'intvl' && this.mouseupNode.nodeTypeRef === 'cp') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDCP'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'cp') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDCP'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'intcp') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDINTCP'));
+ this.deselectPath();
+ } else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'cp') {
+ this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
+ if (vduDetails.id === this.mousedownNode.id) {
+ if (vduDetails.interface === undefined) { vduDetails.interface = []; }
+ vduDetails.interface.push({
+ 'external-connection-point-ref': this.mouseupNode.id, 'mgmt-interface': true,
+ name: 'eth_' + this.sharedService.randomString(),
+ 'virtual-interface': { type: 'VIRTIO' },
+ type: 'EXTERNAL'
+ });
+ if (vduDetails['internal-connection-point'] === undefined) {
+ vduDetails['internal-connection-point'] = [];
+ }
+ if (vduDetails['monitoring-param'] === undefined) {
+ vduDetails['monitoring-param'] = [];
+ }
+ if (vduDetails['vm-flavor'] === undefined) {
+ vduDetails['vm-flavor'] = {};
+ }
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ this.deselectPath();
+ } else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'intvl') {
+ const setIntCP: string = 'intcp_' + this.sharedService.randomString();
+ this.vnfdPackageDetails['internal-vld'].forEach((vldInternal: InternalVLD) => {
+ if (vldInternal.id === this.mouseupNode.id) {
+ if (vldInternal['internal-connection-point'] === undefined) { vldInternal['internal-connection-point'] = []; }
+ vldInternal['internal-connection-point'].push({ 'id-ref': setIntCP });
+ }
+ });
+ this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
+ if (vduDetails.id === this.mousedownNode.id) {
+ if (vduDetails.interface === undefined) {
+ vduDetails.interface = [];
+ }
+ vduDetails.interface.push({
+ 'internal-connection-point-ref': setIntCP, name: 'int_' + setIntCP, type: 'INTERNAL', 'virtual-interface': { type: 'VIRTIO' }
+ });
+ if (vduDetails['internal-connection-point'] === undefined) {
+ vduDetails['internal-connection-point'] = [];
+ }
+ vduDetails['internal-connection-point'].push({
+ id: setIntCP, name: setIntCP, 'short-name': setIntCP, type: 'VPORT'
+ });
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ this.deselectPath();
+ }
+ else {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
+ this.deselectPath();
+ }
+ this.resetMouseActions();
+ this.currentSelectedNode = null;
+ }
+ /** Events handles when mousemove it will capture the selected node data @private */
+ private mousemove(): void {
+ if (!this.mousedownNode) { return; }
+ this.dragLine.attr('d',
+ `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
+ }
+ /** reset Mouse varaibles @private */
+ private resetMouseActions(): void {
+ this.mousedownNode = null;
+ this.mouseupNode = null;
+ }
+ /** Key press event @private */
+ private keyDown(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ if (this.lastKeyDown !== -1) { return; }
+ this.lastKeyDown = d3.event.keyCode;
+ if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
+ this.gNetwork.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
+ this.gVirutualDeploymentUnit.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
+ this.gConnectionPoint.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
+ this.gIntConnectionPoint.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
+ this.svg.classed('ctrl', true);
+ }
+ }
+ /** Key realse event @private */
+ private keyUp(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.lastKeyDown = -1;
+ if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
+ this.gNetwork.on('.drag', null);
+ this.gVirutualDeploymentUnit.on('.drag', null);
+ this.gConnectionPoint.on('.drag', null);
+ this.gIntConnectionPoint.on('.drag', null);
+ this.svg.classed('ctrl', false);
+ }
+ }
+ /** Mosue Drag Line false if it is not satisfied @private */
+ private deselectPath(): void {
+ this.dragLine.classed('hidden', true).attr('d', 'M0,0L0,0');
+ }
+ /** Events handles when Shift Click to perform create cp @private */
+ // tslint:disable-next-line: no-any
+ private singleClick(nodeSelected: any, d: VNFDNODE): void {
+ this.selectedNode(nodeSelected, d);
+ }
+ /** Get confirmation Before Deleting the Node in Topology @private */
+ private getDeleteNodeConfirmation(d: VNFDNODE): void {
+ const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
+ modalRef.componentInstance.topologyType = 'Delete';
+ modalRef.componentInstance.topologyname = d.name;
+ if (d.nodeTypeRef === 'vdu') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VDU';
+ } else if (d.nodeTypeRef === 'intvl') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTVL';
+ } else if (d.nodeTypeRef === 'cp') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
+ } else if (d.nodeTypeRef === 'intcp') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTCP';
+ }
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.deleteNode(d);
+ }
+ }).catch();
+ }
+ /** Delete nodes @private */
+ private deleteNode(d: VNFDNODE): void {
+ const deletedNode: VNFDNODE = d;
+ this.nodes.forEach((node: VNFDNODE) => {
+ if (node.id === d.id) {
+ if (deletedNode.nodeTypeRef === 'cp') {
+ if (this.vnfdPackageDetails.vdu !== undefined) {
+ this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
+ if (vduDetails.interface !== undefined) {
+ const interfacePos: number = vduDetails.interface.map((e: VNFDInterface) => { return e['external-connection-point-ref']; })
+ .indexOf(d.id);
+ if (interfacePos >= 0) {
+ vduDetails.interface.splice(interfacePos, 1);
+ }
+ }
+ });
+ }
+ const cpPos: number = this.vnfdPackageDetails['connection-point'].map((e: CONNECTIONPOINT) => { return e.name; })
+ .indexOf(d.id);
+ if (cpPos >= 0) {
+ this.vnfdPackageDetails['connection-point'].splice(cpPos, 1);
+ }
+ } else if (deletedNode.nodeTypeRef === 'intcp') {
+ this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
+ // Delete Interface
+ const interfacePos: number = vduDetails.interface.map((e: VNFDInterface) => { return e['internal-connection-point-ref']; })
+ .indexOf(d.id);
+ if (interfacePos >= 0) {
+ vduDetails.interface.splice(interfacePos, 1);
+ }
+ // Delete Internal CP
+ const interCPPos: number = vduDetails['internal-connection-point']
+ .map((e: VDUInternalConnectionPoint) => { return e.id; })
+ .indexOf(d.id);
+ if (interCPPos >= 0) {
+ vduDetails['internal-connection-point'].splice(interCPPos, 1);
+ }
+ });
+ if (this.vnfdPackageDetails['internal-vld'] !== undefined && this.vnfdPackageDetails['internal-vld'].length > 0) {
+ this.vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
+ const interfacePos: number = internalVLD['internal-connection-point']
+ .map((e: VLDInternalConnectionPoint) => { return e['id-ref']; }).indexOf(d.id);
+ if (interfacePos >= 0) {
+ internalVLD['internal-connection-point'].splice(interfacePos, 1);
+ }
+ });
+ }
+ } else if (deletedNode.nodeTypeRef === 'intvl') {
+ const intvlPos: number = this.vnfdPackageDetails['internal-vld']
+ .map((e: InternalVLD) => { return e.name; }).indexOf(d.id);
+ if (intvlPos >= 0) {
+ this.vnfdPackageDetails['internal-vld'].splice(intvlPos, 1);
+ }
+ } else if (deletedNode.nodeTypeRef === 'vdu') {
+ const internalCPList: string[] = [];
+ if (deletedNode.interface !== undefined && deletedNode.interface.length > 0) {
+ deletedNode.interface.forEach((interfaceNode: InternalVLD) => {
+ if (interfaceNode['internal-connection-point-ref'] !== undefined) {
+ internalCPList.push(interfaceNode['internal-connection-point-ref']);
+ }
+ });
+ }
+ internalCPList.forEach((list: string) => {
+ if (this.vnfdPackageDetails['internal-vld'] !== undefined && this.vnfdPackageDetails['internal-vld'].length > 0) {
+ this.vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
+ const interfacePos: number = internalVLD['internal-connection-point']
+ .map((e: VLDInternalConnectionPoint) => { return e['id-ref']; }).indexOf(list);
+ if (interfacePos >= 0) {
+ internalVLD['internal-connection-point'].splice(interfacePos, 1);
+ }
+ });
+ }
+ });
+ const vduPos: number = this.vnfdPackageDetails.vdu.map((e: VDU) => { return e.id; }).indexOf(d.id);
+ if (vduPos >= 0) {
+ this.vnfdPackageDetails.vdu.splice(vduPos, 1);
+ }
+ } else {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
+ }
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ });
+ }
+ /** Get confirmation before deleting the ink in Topology @private */
+ private getDeleteLinkConfirmation(d: Tick): void {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.YOUCANNOTDELETELINK'));
+ }
+ /** Selected nodes @private */
+ // tslint:disable-next-line: no-any
+ private selectedNode(nodeSeleced: any, d: VNFDNODE): void {
+ const alreadyIsActive: boolean = nodeSeleced.select('#' + d.id).classed(this.activeNode);
+ this.deselectAllNodes();
+ nodeSeleced.select('#' + d.id).classed(this.activeNode, !alreadyIsActive);
+ if (d.nodeTypeRef === 'vdu' && !alreadyIsActive) {
+ this.vnfdPackageDetails.vdu.forEach((res: VDU) => {
+ if (res.name === d.id) {
+ this.showRightSideInfo = 'vduInfo';
+ this.vduInfo = res;
+ }
+ });
+ } else if (d.nodeTypeRef === 'intvl' && !alreadyIsActive) {
+ this.vnfdPackageDetails['internal-vld'].forEach((res: InternalVLD) => {
+ if (res.name === d.id) {
+ this.showRightSideInfo = 'intvlInfo';
+ this.intvlInfo = res;
+ this.intvlInfo.shortName = res['short-name'];
+ this.intvlInfo.ipProfileRef = res['ip-profile-ref'];
+ }
+ });
+ } else if (d.nodeTypeRef === 'cp' && !alreadyIsActive) {
+ this.vnfdPackageDetails['connection-point'].forEach((res: CONNECTIONPOINT) => {
+ if (res.name === d.id) {
+ this.showRightSideInfo = 'cpInfo';
+ this.cpInfo = res;
+ }
+ });
+ }
+ else if (d.nodeTypeRef === 'intcp' && !alreadyIsActive) {
+ this.intcpInfo = d;
+ this.showRightSideInfo = 'intcpInfo';
+ this.intcpInfo.shortName = d['short-name'];
+ } else {
+ this.showRightSideInfo = 'vnfdInfo';
+ }
+ }
+ /** De-select all the selected nodes @private */
+ private deselectAllNodes(): void {
+ this.network.select('image').classed(this.activeNode, false);
+ this.virutualDeploymentUnit.select('image').classed(this.activeNode, false);
+ this.connectionPoint.select('image').classed(this.activeNode, false);
+ this.intConnectionPoint.select('image').classed(this.activeNode, false);
+ }
+ /** Events handles when dragstarted @private */
+ private dragstarted(d: COMPOSERNODES): void {
+ d.fx = d.x;
+ d.fy = d.y;
+ }
+ /** Events handles when dragged @private */
+ private dragged(d: COMPOSERNODES): void {
+ d.fx = d.x = d3.event.x;
+ d.fy = d.y = d3.event.y;
+ }
+ /** Events handles when dragended @private */
+ private dragended(d: COMPOSERNODES): void {
+ if (this.forceSimulationActive) {
+ d.fx = null;
+ d.fy = null;
+ } else {
+ d.fx = d.x;
+ d.fy = d.y;
+ this.forceSimulationActive = false;
+ }
+ }
+ /** Events handles when node double click @private */
+ private onNodedblClickToggleSidebar(): void {
+ this.sideBarOpened = false;
+ }
+ /** Events handles when node single click @private */
+ private onNodeClickToggleSidebar(): void {
+ this.sideBarOpened = true;
+ }
+}