From 6f900cc45d7dd7f97430812b86b5c1d1693c8ae3 Mon Sep 17 00:00:00 2001 From: Ittay Stern Date: Wed, 29 Aug 2018 17:01:32 +0300 Subject: merge from ecomp a88f0072 - Modern UI Issue-ID: VID-378 Change-Id: Ibcb23dd27f550cf32ce2fe0239f0f496ae014ff6 Signed-off-by: Ittay Stern --- .../available-models-tree.component.html | 47 ++ .../available-models-tree.component.scss | 506 +++++++++++++++++++++ .../available-models-tree.component.ts | 167 +++++++ .../available-models-tree.service.spec.ts | 427 +++++++++++++++++ .../available-models-tree.service.ts | 76 ++++ 5 files changed, 1223 insertions(+) create mode 100644 vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.html create mode 100644 vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.scss create mode 100644 vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts create mode 100644 vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.spec.ts create mode 100644 vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.ts (limited to 'vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree') diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.html b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.html new file mode 100644 index 000000000..91acca0d1 --- /dev/null +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.html @@ -0,0 +1,47 @@ +
+
+
+ MODEL (from SDC): + {{service | serviceInfo: _store: serviceModelId : 'name'}} +
+ +
+
+ + +
+ {{node?.data?.typeName}} +
+ + + + + +
+ + + {{node.data.getNodeCount(node, this.serviceModelId)}} + + + + + + + + + + + +
+
+
+
+
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.scss b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.scss new file mode 100644 index 000000000..90c2cd878 --- /dev/null +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.scss @@ -0,0 +1,506 @@ +.tree-children.tree-children-no-padding { padding-left: 0 } +.tree-children { padding-left: 20px; overflow: hidden } +.node-drop-slot { display: block; height: 2px } +.node-drop-slot.is-dragging-over { background: #ddffee; height: 20px; border: 2px dotted #888; } +.toggle-children-wrapper-expanded .toggle-children { transform: rotate(90deg) } +.toggle-children-wrapper-collapsed .toggle-children { transform: rotate(0); } +.toggle-children-wrapper { + padding: 2px 3px 5px 1px; +} +/* tslint:disable */ +.toggle-children { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABAhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDY3IDc5LjE1Nzc0NywgMjAxNS8wMy8zMC0yMzo0MDo0MiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjY1RTYzOTA2ODZDRjExREJBNkUyRDg4N0NFQUNCNDA3IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkYzRkRFQjcxODUzNTExRTU4RTQwRkQwODFEOUZEMEE3IiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkYzRkRFQjcwODUzNTExRTU4RTQwRkQwODFEOUZEMEE3IiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MTk5NzA1OGEtZDI3OC00NDZkLWE4ODgtNGM4MGQ4YWI1NzNmIiBzdFJlZjpkb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6YzRkZmQxMGMtY2NlNS0xMTc4LWE5OGQtY2NkZmM5ODk5YWYwIi8+IDxkYzp0aXRsZT4gPHJkZjpBbHQ+IDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+Z2x5cGhpY29uczwvcmRmOmxpPiA8L3JkZjpBbHQ+IDwvZGM6dGl0bGU+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+5iogFwAAAGhJREFUeNpiYGBgKABigf///zOQg0EARH4A4gZyDIIZ8B/JoAJKDIDhB0CcQIkBRBtEyABkgxwoMQCGD6AbRKoBGAYxQgXIBRuZGKgAKPIC3QLxArnRSHZCIjspk52ZKMrOFBUoAAEGAKnq593MQAZtAAAAAElFTkSuQmCC'); + height: 8px; + width: 9px; + background-size: contain; + display: inline-block; + position: relative; + top: 1px; + background-repeat: no-repeat; + background-position: center; +} +.toggle-children-placeholder { + display: inline-block; + height: 10px; + width: 10px; + position: relative; + top: 1px; + padding-right: 3px; +} +.node-content-wrapper { + display: inline-block; + padding: 2px 5px; + border-radius: 2px; + transition: background-color .15s,box-shadow .15s; +} +.node-wrapper {display: flex; align-items: flex-start;} +.node-content-wrapper-active, +.node-content-wrapper.node-content-wrapper-active:hover, +.node-content-wrapper-active.node-content-wrapper-focused { + background: #beebff; +} +.node-content-wrapper-focused { background: #e7f4f9 } +.node-content-wrapper:hover { background: #f7fbff } +.node-content-wrapper-active, .node-content-wrapper-focused, .node-content-wrapper:hover { + box-shadow: inset 0 0 1px #999; +} +.node-content-wrapper.is-dragging-over { background: #ddffee; box-shadow: inset 0 0 1px #999; } +.node-content-wrapper.is-dragging-over-disabled { opacity: 0.5 } + +tree-viewport { + height: 100%; + overflow: auto; + display: block; +} +.tree-children { padding-left: 20px } +.empty-tree-drop-slot .node-drop-slot { height: 20px; min-width: 100px } +.angular-tree-component { + width: 100%; + position:relative; + display: inline-block; + cursor: pointer; + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Chrome/Safari/Opera */ + -khtml-user-select: none; /* Konqueror */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE/Edge */ + user-select: none; /* non-prefixed version, currently not supported by any browser */ +} + +tree-root .angular-tree-component-rtl { + direction: rtl; +} +tree-root .angular-tree-component-rtl .toggle-children-wrapper-collapsed .toggle-children { + transform: rotate(180deg) !important; +} +tree-root .angular-tree-component-rtl .tree-children { + padding-right: 20px; + padding-left: 0; +} + +tree-node-checkbox { + padding: 1px; +} + + +available-models-tree { + height: 100%; + &.left-side{ + background: #F2F2F2; + padding: 0; + border-right: #D2D2D2 1px solid; + max-width: 690px; + } + + .available-models-tree { + display: flex; + flex-direction: column; + line-height: 14px; + min-width: 340px; + padding: 30px; + height: 100%; + .models-tree-header { + display: flex; + justify-content: space-between; + + h5 { + margin: 0; + font-family: OpenSans-Semibold; + color: #191919; + font-size: 16px; + + span { + vertical-align: middle; + display: inline-block; + font-size: 16px; + color: #191919; + line-height: 16px; + &.sub-title { + font-family: OpenSans-Regular; + font-size: 14px; + color: #0D0D0D; + } + } + + #service-model-name { + padding-top: 5px; + display: block; + font-size: 14px; + } + } + + .search-container { + width: 275px; + } + } + .available-models-content-wrapper { + flex: 1; + display: flex; + flex-direction: column; + margin-top: 20px; + + + tree-root { + flex: 1; + display: flex; + } + tree-viewport { + flex: 1; + .tree-node { + color: #5A5A5A; + font-size: 13px; + white-space: normal; + word-break: break-all; + tree-node-drop-slot { + .node-drop-slot { + display: none; + } + } + &.tree-node-disabled { + color: #D2D2D2; + cursor: default; + pointer-events: none; + } + &:not(.tree-node-disabled) { + >tree-node-wrapper { + .node-wrapper:hover { + color: #191919; + .node-content-wrapper.node-content-wrapper-focused { + tree-node-content { + > div { + background: #009FDB; + color: white; + } + } + } + .node-content-wrapper { + tree-node-content { + > div { + background: #F2F2F2; + &.tree-node-focused:not(.tree-node-disabled) { + background: #009FDB; + color: white; + } + span.actions { + .icon-plus{ + display: block; + color: #009FDB; + span:before { + display: inline-block; + color: #5A5A5A; + } + } + } + } + } + } + } + } + } + &.tree-node-focused:not(.tree-node-disabled) { + & > tree-node-wrapper { + .node-wrapper { + border-color: #1EB9F3; + .node-content-wrapper{ + background: #009FDB; + border-color: #1EB9F3; + } + .node-content-wrapper-focused{ + box-shadow: none; + tree-node-content { + + .vf-type{ + color: #ffffff; + border-color: #1EB9F3; + } + > div { + span.actions { + .icon-plus { + color: #ffffff; + } + } + } + } + } + } + } + } + tree-node-wrapper { + .node-wrapper { + height: 36px; + tree-node-expander { + font-family: 'icomoon' !important; + height: 100%; + .toggle-children-wrapper { + padding: 0; + display: block; + height: 100%; + span.toggle-children { + display: flex; + width: 20px; + top: 0; + height: inherit; + background-image: none; + &:before { + content: "\e900"; + font-weight: 600; + text-align: center; + display: inline-block; + flex: auto; + align-self: center; + font-size: 20px; + } + } + } + .toggle-children-wrapper-expanded { + span.toggle-children { + transform: none; + &:before { + content: "\e930"; + } + } + } + .toggle-children-placeholder { + width: 20px; + } + } + .node-content-wrapper { + padding: 0; + background: none; + box-shadow: none; + height: 100%; + flex: 1; + min-width: 0; + border-left: 1px solid #D2D2D2; + tree-node-content { + > div { + height: 100%; + display: flex; + align-items: center; + justify-content: space-between; + span { + &.actions { + height: 100%; + display: flex; + justify-content: space-between; + align-items: center; + >span { + width: 45px; + max-width: 45px; + text-align: center; + } + .number-button { + width: 30px; + padding-left: 0; + text-align: center; + span { + display: block; + font-family: OpenSans-SemiBold; + font-size: 13px; + color: #5A5A5A; + line-height: 16px; + } + } + .icon-plus { + display: none; + width: 45px; + font-size: 22px; + } + } + } + } + } + } + + } + } + } + & > tree-node-collection > tree-node > .node-wrapper{ + //border-top: 1px solid #D2D2D2; + } + } + + } + } +} +.highlight { + background-color: #9DD9EF; +} + +#drawing-board-tree{ + .tree-node.tree-node-expanded.tree-node-focused { + } +} + +available-models-tree { + + .tree-root { + margin-top: 35px; + } + + tree-node-expander { + background: #FFFFFF; + border: 1px solid #D2D2D2; + border-right: none; + width: 45px; + padding-left: 12px; + } + + .node-content-wrapper { + border: none; + } + + tree-node-wrapper tree-node-expander{ + background: none !important; + border: none !important; + } + + + .node-wrapper { + height: 45px !important; + background: #FFFFFF; + border: 1px solid #D2D2D2; + } + + tree-node-collection div { + margin-top: 0px; + } + + .tree-node-leaf .node-wrapper tree-node-expander { + display: none; + } + + .tree-node.tree-node-expanded { + margin-bottom: 10px; + } + .tree-node-collapsed { + margin-bottom: 10px; + } + .tree-children { + padding-left: 0; + } + + tree-node-content .actions .number-button { + height: 45px; + padding-top: 14px; + border-right: 1px solid #D2D2D2; + border-left: 1px solid #D2D2D2; + padding-left: 0; + span { + background: none; + font-size: 11px; + color: #5A5A5A; + } + } + + .node-content-wrapper.node-content-wrapper-focused{ + border-color:#1EB9F3 ; + tree-node-content > div{ + .vf-type,.model-info,.model-info .property-name { + color: white; + } + .number-button{ + border-color: #1EB9F3 ; + span{ + color: white !important; + } + } + + } + } + + + + .vf-type { + width: 40px; + height: 45px; + padding-top: 16px; + border-right: 1px solid #D2D2D2; + color: #959595; + font-size: 13px; + font-family: OpenSans-SemiBold; + text-transform: uppercase; + text-align: center; + flex-basis: 40px; + flex-grow: 0; + flex-shrink: 0; + } + + .isParent { + width: 100%; + padding-left: 0 !important; + } + .model-info { + padding-left: 16px; + width: 100%; + .property-name { + font-family: OpenSans-Regular; + font-size: 12px; + line-height: 12px; + color: #191919; + //text-transform: capitalize; problematic with search + .auto-name{ + display: inline-flex;//required for search more then one sub highlight + } + } + + tree-node-header-properties { + display: none; + } + } + + .span-name { + margin-right: auto; + padding-left: 10px; + } + + .toggle-children-wrapper.toggle-children-wrapper-expanded { + .toggle-children:before { + color: #009FDB; + } + } + + .tree-node.tree-node-expanded .tree-children { + } + + .tree-node.tree-node-expanded.tree-node-focused .tree-children { + + } + + .tree-node.tree-node-expanded > tree-node-wrapper{ + box-shadow: 0 2px 2px 0 rgba(0,0,0,.1); + position: relative; + z-index: 1; + display: block; + } + + .tree-node-leaf .node-wrapper{ + margin-left: 46px; + border-left: none; + } + .tree-children .tree-node-leaf .node-wrapper{ + margin-left: 86px; + } +} + +@media (max-width: 992px) { + available-models-tree{ + //width: 40%; + max-width: 690px; + } + drawing-board-tree{ + //width: 60%; + } +} + +@media (min-width: 992px) { + available-models-tree{ + //width: 50%; + max-width: 650px; + } + drawing-board-tree{ + //width: 50%; + } +} + + diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts new file mode 100644 index 000000000..31d7b03b8 --- /dev/null +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts @@ -0,0 +1,167 @@ +import {Component, EventEmitter, Output, ViewChild} from '@angular/core'; +import {ITreeOptions, TreeComponent} from 'angular-tree-component'; +import {IDType, ITreeNode} from 'angular-tree-component/dist/defs/api'; +import {DialogService} from 'ng2-bootstrap-modal'; +import {AvailableModelsTreeService} from './available-models-tree.service'; +import {NgRedux} from "@angular-redux/store"; +import {ActivatedRoute} from '@angular/router'; +import {AppState} from '../../../shared/store/reducers'; +import {AaiService} from '../../../shared/services/aaiService/aai.service'; +import {ServiceNodeTypes} from '../../../shared/models/ServiceNodeTypes'; +import {IframeService} from "../../../shared/utils/iframe.service"; +import {DefaultDataGeneratorService} from "../../../shared/services/defaultDataServiceGenerator/default.data.generator.service"; +import {VfModulePopuopService} from "../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service"; +import {NetworkPopupService} from "../../../shared/components/genericFormPopup/genericFormServices/network/network.popup.service"; +import {createVFModuleInstance} from "../../../shared/storeUtil/utils/vfModule/vfModule.actions"; +import {VnfPopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service"; +import {DrawingBoardModes} from "../drawing-board.modes"; +import {DrawingBoardTreeService} from "../drawing-board-tree/drawing-board-tree.service"; +import {ObjectToModelTreeService} from "../objectsToTree/objectToModelTree/objectToModelTree.service"; +import {VnfGroupPopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service"; +import {SharedTreeService} from "../objectsToTree/shared.tree.service"; +import {changeInstanceCounter} from "../../../shared/storeUtil/utils/general/general.actions"; +import {createVnfGroupInstance} from "../../../shared/storeUtil/utils/vnfGroup/vnfGroup.actions"; +import {VnfGroupControlGenerator} from "../../../shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator"; +import {HighlightPipe} from "../../../shared/pipes/highlight/highlight-filter.pipe"; +import * as _ from 'lodash'; +import {DrawingBoardTreeComponent} from "../drawing-board-tree/drawing-board-tree.component"; + + +@Component({ + selector: 'available-models-tree', + templateUrl: './available-models-tree.component.html', + styleUrls: ['./available-models-tree.component.scss'], + providers : [HighlightPipe] +}) + +export class AvailableModelsTreeComponent { + filterValue : string = ''; + serviceModelId: string; + serviceHierarchy; + parentElementClassName = 'content'; + _store: NgRedux; + isNewObject: boolean; + availableModelsTreeService: AvailableModelsTreeService; + drawingBoardTreeService: DrawingBoardTreeService; + + constructor(private _iframeService: IframeService, + private _aaiService: AaiService, + private route: ActivatedRoute, + private dialogService: DialogService, + private _availableModelsTreeService: AvailableModelsTreeService, + private _drawingBoardTreeService: DrawingBoardTreeService, + private _defaultDataGeneratorService: DefaultDataGeneratorService, + private _vnfGroupControlGenerator: VnfGroupControlGenerator, + private _vfModulePopuopService: VfModulePopuopService, + private _vnfGroupPopupService: VnfGroupPopupService, + private _vnfPopupService: VnfPopupService, + private _networkPopupService: NetworkPopupService, + private store: NgRedux, + private _objectToModelTreeService : ObjectToModelTreeService, + private _sharedTreeService : SharedTreeService, + private _highlightPipe : HighlightPipe) { + this.availableModelsTreeService = _availableModelsTreeService; + this.drawingBoardTreeService = _drawingBoardTreeService; + + this._store = store; + this.route + .queryParams + .subscribe(params => { + this.serviceModelId = params['serviceModelId']; + this._aaiService.getServiceModelById(this.serviceModelId).subscribe( + value => { + this.serviceHierarchy = value; + this.nodes = this._objectToModelTreeService.convertServiceHierarchyModelToTreeNodes(this.serviceHierarchy); + }, + error => { + console.log('error is ', error) + } + ); + }); + + } + + @Output() + highlightInstances: EventEmitter = new EventEmitter(); + @ViewChild('tree') tree: TreeComponent; + + nodes = []; + service = {name: ''}; + + options: ITreeOptions = { + nodeHeight: 36, + dropSlotHeight: 0, + nodeClass: (node: ITreeNode) => { + if (node.data.type === ServiceNodeTypes.VFmodule && ! node.parent.data['getNodeCount'](node.parent, this.serviceModelId) && this.store.getState().global.drawingBoardStatus !== DrawingBoardModes.VIEW) { + node.data.disabled = true; + return 'tree-node tree-node-disabled'; + } + node.data.disabled = false; + return 'tree-node'; + } + }; + + + getNodeName(node : ITreeNode, filter : string) { + return this._highlightPipe.transform(node.data.name ,filter ? filter : ''); + } + + expandParentByNodeId(id: IDType): void { + this.tree.treeModel.getNodeById(id).parent.expand(); + } + + updateNodes(updateData : {nodes : any, filterValue : string}) : void { + this.nodes = updateData.nodes; + this.filterValue = updateData.filterValue; + } + + selectNode(node: ITreeNode): void { + node.expand(); + this._sharedTreeService.setSelectedVNF(null); + this.highlightInstances.emit(node.data.modelUniqueId); + } + + + + onClickAdd(node: ITreeNode, serviceId: string , isNewObject: boolean = false): void { + this.isNewObject = isNewObject; + let data = node.data; + let dynamicInputs = data.dynamicInputs; + let isAlaCarte: boolean = this.serviceHierarchy.service.instantiationType == "A-La-Carte"; + let isEcompGeneratedNaming: boolean = data.isEcompGeneratedNaming; + let type: string = data.type; + if (!this.store.getState().global.flags['FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD'] || node.data.type === ServiceNodeTypes.VF || + this._availableModelsTreeService.shouldOpenDialog(type, dynamicInputs, isEcompGeneratedNaming)) { + this._iframeService.addClassOpenModal(this.parentElementClassName); + node.data.onAddClick(node, serviceId); + } else { + if (node.data.type === ServiceNodeTypes.VnfGroup) { + let instanceName = this._vnfGroupControlGenerator.getDefaultInstanceName(null, serviceId, node.data.name); + let vnfGroup = this._defaultDataGeneratorService.generateVnfGroupInstance(this.serviceHierarchy.vnfGroups[node.data.name], isEcompGeneratedNaming, isAlaCarte, instanceName); + this._store.dispatch(changeInstanceCounter(node.data.modelUniqueId, serviceId, 1 , {data: {type: 'VnfGroup'}})); + this._store.dispatch(createVnfGroupInstance(vnfGroup, node.data.name, serviceId, node.data.name)); + DrawingBoardTreeComponent.triggerreCalculateIsDirty.next(this.serviceModelId); + } else { + let vfModule = this._defaultDataGeneratorService.generateVFModule(this.serviceHierarchy.vnfs[node.parent.data.name].vfModules[node.data.name], dynamicInputs, isEcompGeneratedNaming, isAlaCarte); + if (this._sharedTreeService.selectedVNF) { + this.store.dispatch(createVFModuleInstance(vfModule, node.data.name, this.serviceModelId, null, this._sharedTreeService.selectedVNF)); + DrawingBoardTreeComponent.triggerreCalculateIsDirty.next(this.serviceModelId); + } else if (this._availableModelsTreeService.getOptionalVNFs(this.serviceModelId, node.parent.data.name).length === 1) { + let existVnf = this._store.getState().service.serviceInstance[this.serviceModelId].vnfs; + if(!_.isNil(existVnf)){ + for(let vnfKey in existVnf){ + if(existVnf[vnfKey]['modelInfo'].modelUniqueId === node.parent.data.id){ + this.store.dispatch(createVFModuleInstance(vfModule, node.data.name, this.serviceModelId, null, vnfKey)); + DrawingBoardTreeComponent.triggerreCalculateIsDirty.next(this.serviceModelId); + } + } + } + + + } else { + this._availableModelsTreeService.addingAlertAddingNewVfModuleModal(); + } + } + } + } +} diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.spec.ts new file mode 100644 index 000000000..cf9d04aae --- /dev/null +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.spec.ts @@ -0,0 +1,427 @@ +import {TestBed, getTestBed} from '@angular/core/testing'; +import { + HttpClientTestingModule, + HttpTestingController +} from '@angular/common/http/testing'; +import {AvailableModelsTreeService, AvailableNodeIcons} from './available-models-tree.service'; +import {ServiceNodeTypes} from "../../../shared/models/ServiceNodeTypes"; +import {DefaultDataGeneratorService} from "../../../shared/services/defaultDataServiceGenerator/default.data.generator.service"; +import {MessageBoxService} from "../../../shared/components/messageBox/messageBox.service"; +import {MessageBoxData} from "../../../shared/components/messageBox/messageBox.data"; +import {SdcUiCommon} from "onap-ui-angular"; +import {MockNgRedux, NgReduxTestingModule} from "@angular-redux/store/testing"; +import {SharedTreeService} from "../objectsToTree/shared.tree.service"; + +describe('Available Models Tree Service', () => { + + let injector; + let service: AvailableModelsTreeService; + let httpMock: HttpTestingController; + + beforeAll(done => (async () => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule, NgReduxTestingModule], + providers: [AvailableModelsTreeService, + DefaultDataGeneratorService, + SharedTreeService, + MockNgRedux] + }); + await TestBed.compileComponents(); + injector = getTestBed(); + service = injector.get(AvailableModelsTreeService); + httpMock = injector.get(HttpTestingController); + })().then(done).catch(done.fail)); + + + test('addingAlertAddingNewVfModuleModal should open message modal', () => { + jest.spyOn(MessageBoxService.openModal, 'next'); + service.addingAlertAddingNewVfModuleModal(); + + expect(MessageBoxService.openModal.next).toHaveBeenCalledWith(new MessageBoxData( + "Select a parent", // modal title + "There are multiple instances on the right side that can contain this vf-module Please select the VNF instance, to add this vf-module to, on the right side and then click the + sign", + SdcUiCommon.ModalType.warning, + SdcUiCommon.ModalSize.medium, + [ + {text: "Close", size: "medium", closeModal: true} + ])); + }); + + + + describe('#shouldOpenModalDialogOnAddInstance', () => { + let serviceHierarchy = getServiceServiceHierarchy(); + + test('should open popup on add instance', () => { + // add vnf should return true + let result = service.shouldOpenDialog(ServiceNodeTypes.VF, [], true); + expect(result).toBeTruthy(); + + // add vfModule with user provided naming should return true + result = service.shouldOpenDialog(ServiceNodeTypes.VFmodule, [], false); + expect(result).toBeTruthy(); + + // add vfModule with dynamicInputs without defaultValues should return true + result = service.shouldOpenDialog(ServiceNodeTypes.VFmodule, [{ + id: '2017488_adiodvpe0_vnf_config_template_version', + type: 'string', + name: '2017488_adiodvpe0_vnf_config_template_version', + isRequired: true, + description: 'VPE Software Version' + }], true); + expect(result).toBeTruthy(); + + // add vfModule with dynamicInputs with defaultValues should return false + result = service.shouldOpenDialog(ServiceNodeTypes.VFmodule, [{ + id: '2017488_adiodvpe0_vnf_config_template_version', + type: 'string', + name: '2017488_adiodvpe0_vnf_config_template_version', + value: '17.2', + isRequired: true, + description: 'VPE Software Version' + }], true); + expect(result).toBeFalsy(); + }); + }); + + function getServiceServiceHierarchy() { + return JSON.parse(JSON.stringify( + { + '6e59c5de-f052-46fa-aa7e-2fca9d674c44': { + 'service': { + 'uuid': '6e59c5de-f052-46fa-aa7e-2fca9d674c44', + 'invariantUuid': 'e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0', + 'name': 'ComplexService', + 'version': '1.0', + 'toscaModelURL': null, + 'category': 'Emanuel', + 'serviceType': '', + 'serviceRole': '', + 'description': 'ComplexService', + 'serviceEcompNaming': 'true', + 'instantiationType': 'Macro', + 'inputs': {} + }, + 'vnfs': { + 'VF_vMee 0': { + 'uuid': 'd6557200-ecf2-4641-8094-5393ae3aae60', + 'invariantUuid': '4160458e-f648-4b30-a176-43881ffffe9e', + 'description': 'VSP_vMee', + 'name': 'VF_vMee', + 'version': '2.0', + 'customizationUuid': '91415b44-753d-494c-926a-456a9172bbb9', + 'inputs': {}, + 'commands': {}, + 'properties': { + 'max_instances': '3', + 'min_instances': '1', + 'gpb2_Internal2_mac': '00:11:22:EF:AC:DF', + 'sctp-b-ipv6-egress_src_start_port': '0', + 'sctp-a-ipv6-egress_rule_application': 'any', + 'Internal2_allow_transit': 'true', + 'sctp-b-IPv6_ethertype': 'IPv6', + 'sctp-a-egress_rule_application': 'any', + 'sctp-b-ingress_action': 'pass', + 'sctp-b-ingress_rule_protocol': 'icmp', + 'ncb2_Internal1_mac': '00:11:22:EF:AC:DF', + 'sctp-b-ipv6-ingress-src_start_port': '0.0', + 'ncb1_Internal2_mac': '00:11:22:EF:AC:DF', + 'fsb_volume_size_0': '320.0', + 'sctp-b-egress_src_addresses': 'local', + 'sctp-a-ipv6-ingress_ethertype': 'IPv4', + 'sctp-a-ipv6-ingress-dst_start_port': '0', + 'sctp-b-ipv6-ingress_rule_application': 'any', + 'domain_name': 'default-domain', + 'sctp-a-ingress_rule_protocol': 'icmp', + 'sctp-b-egress-src_start_port': '0.0', + 'sctp-a-egress_src_addresses': 'local', + 'sctp-b-display_name': 'epc-sctp-b-ipv4v6-sec-group', + 'sctp-a-egress-src_start_port': '0.0', + 'sctp-a-ingress_ethertype': 'IPv4', + 'sctp-b-ipv6-ingress-dst_end_port': '65535', + 'sctp-b-dst_subnet_prefix_v6': '::', + 'nf_naming': '{ecomp_generated_naming=true}', + 'sctp-a-ipv6-ingress_src_subnet_prefix': '0.0.0.0', + 'sctp-b-egress-dst_start_port': '0.0', + 'ncb_flavor_name': 'nv.c20r64d1', + 'gpb1_Internal1_mac': '00:11:22:EF:AC:DF', + 'sctp-b-egress_dst_subnet_prefix_len': '0.0', + 'Internal2_net_cidr': '10.0.0.10', + 'sctp-a-ingress-dst_start_port': '0.0', + 'sctp-a-egress-dst_start_port': '0.0', + 'fsb1_Internal2_mac': '00:11:22:EF:AC:DF', + 'sctp-a-egress_ethertype': 'IPv4', + 'vlc_st_service_mode': 'in-network-nat', + 'sctp-a-ipv6-egress_ethertype': 'IPv4', + 'sctp-a-egress-src_end_port': '65535.0', + 'sctp-b-ipv6-egress_rule_application': 'any', + 'sctp-b-egress_action': 'pass', + 'sctp-a-ingress-src_subnet_prefix_len': '0.0', + 'sctp-b-ipv6-ingress-src_end_port': '65535.0', + 'sctp-b-name': 'epc-sctp-b-ipv4v6-sec-group', + 'fsb2_Internal1_mac': '00:11:22:EF:AC:DF', + 'sctp-a-ipv6-ingress-src_start_port': '0.0', + 'sctp-b-ipv6-egress_ethertype': 'IPv4', + 'Internal1_net_cidr': '10.0.0.10', + 'sctp-a-egress_dst_subnet_prefix': '0.0.0.0', + 'fsb_flavor_name': 'nv.c20r64d1', + 'sctp_rule_protocol': '132', + 'sctp-b-ipv6-ingress_src_subnet_prefix_len': '0', + 'sctp-a-ipv6-ingress_rule_application': 'any', + 'sctp-a-IPv6_ethertype': 'IPv6', + 'vlc2_Internal1_mac': '00:11:22:EF:AC:DF', + 'vlc_st_virtualization_type': 'virtual-machine', + 'sctp-b-ingress-dst_start_port': '0.0', + 'sctp-b-ingress-dst_end_port': '65535.0', + 'sctp-a-ipv6-ingress-src_end_port': '65535.0', + 'sctp-a-display_name': 'epc-sctp-a-ipv4v6-sec-group', + 'sctp-b-ingress_rule_application': 'any', + 'int2_sec_group_name': 'int2-sec-group', + 'vlc_flavor_name': 'nd.c16r64d1', + 'sctp-b-ipv6-egress_src_addresses': 'local', + 'vlc_st_interface_type_int1': 'other1', + 'sctp-b-egress-src_end_port': '65535.0', + 'sctp-a-ipv6-egress-dst_start_port': '0', + 'vlc_st_interface_type_int2': 'other2', + 'sctp-a-ipv6-egress_rule_protocol': 'any', + 'Internal2_shared': 'false', + 'sctp-a-ipv6-egress_dst_subnet_prefix_len': '0', + 'Internal2_rpf': 'disable', + 'vlc1_Internal1_mac': '00:11:22:EF:AC:DF', + 'sctp-b-ipv6-egress_src_end_port': '65535', + 'sctp-a-ipv6-egress_src_addresses': 'local', + 'sctp-a-ingress-dst_end_port': '65535.0', + 'sctp-a-ipv6-egress_src_end_port': '65535', + 'Internal1_forwarding_mode': 'l2', + 'Internal2_dhcp': 'false', + 'sctp-a-dst_subnet_prefix_v6': '::', + 'pxe_image_name': 'MME_PXE-Boot_16ACP04_GA.qcow2', + 'vlc_st_interface_type_gtp': 'other0', + 'ncb1_Internal1_mac': '00:11:22:EF:AC:DF', + 'sctp-b-src_subnet_prefix_v6': '::', + 'sctp-a-egress_dst_subnet_prefix_len': '0.0', + 'int1_sec_group_name': 'int1-sec-group', + 'Internal1_dhcp': 'false', + 'sctp-a-ipv6-egress_dst_end_port': '65535', + 'Internal2_forwarding_mode': 'l2', + 'fsb2_Internal2_mac': '00:11:22:EF:AC:DF', + 'sctp-b-egress_dst_subnet_prefix': '0.0.0.0', + 'Internal1_net_cidr_len': '17', + 'gpb2_Internal1_mac': '00:11:22:EF:AC:DF', + 'sctp-b-ingress-src_subnet_prefix_len': '0.0', + 'sctp-a-ingress_dst_addresses': 'local', + 'sctp-a-egress_action': 'pass', + 'fsb_volume_type_0': 'SF-Default-SSD', + 'ncb2_Internal2_mac': '00:11:22:EF:AC:DF', + 'vlc_st_interface_type_sctp_a': 'left', + 'vlc_st_interface_type_sctp_b': 'right', + 'sctp-a-src_subnet_prefix_v6': '::', + 'vlc_st_version': '2', + 'sctp-b-egress_ethertype': 'IPv4', + 'sctp-a-ingress_rule_application': 'any', + 'gpb1_Internal2_mac': '00:11:22:EF:AC:DF', + 'instance_ip_family_v6': 'v6', + 'sctp-a-ipv6-egress_src_start_port': '0', + 'sctp-b-ingress-src_start_port': '0.0', + 'sctp-b-ingress_dst_addresses': 'local', + 'fsb1_Internal1_mac': '00:11:22:EF:AC:DF', + 'vlc_st_interface_type_oam': 'management', + 'multi_stage_design': 'false', + 'oam_sec_group_name': 'oam-sec-group', + 'Internal2_net_gateway': '10.0.0.10', + 'sctp-a-ipv6-ingress-dst_end_port': '65535', + 'sctp-b-ipv6-egress-dst_start_port': '0', + 'Internal1_net_gateway': '10.0.0.10', + 'sctp-b-ipv6-egress_rule_protocol': 'any', + 'gtp_sec_group_name': 'gtp-sec-group', + 'sctp-a-ipv6-egress_dst_subnet_prefix': '0.0.0.0', + 'sctp-b-ipv6-egress_dst_subnet_prefix_len': '0', + 'sctp-a-ipv6-ingress_dst_addresses': 'local', + 'sctp-a-egress_rule_protocol': 'icmp', + 'sctp-b-ipv6-egress_action': 'pass', + 'sctp-a-ipv6-egress_action': 'pass', + 'Internal1_shared': 'false', + 'sctp-b-ipv6-ingress_rule_protocol': 'any', + 'Internal2_net_cidr_len': '17', + 'sctp-a-name': 'epc-sctp-a-ipv4v6-sec-group', + 'sctp-a-ingress-src_end_port': '65535.0', + 'sctp-b-ipv6-ingress_src_subnet_prefix': '0.0.0.0', + 'sctp-a-egress-dst_end_port': '65535.0', + 'sctp-a-ingress_action': 'pass', + 'sctp-b-egress_rule_protocol': 'icmp', + 'sctp-b-ipv6-ingress_action': 'pass', + 'vlc_st_service_type': 'firewall', + 'sctp-b-ipv6-egress_dst_end_port': '65535', + 'sctp-b-ipv6-ingress-dst_start_port': '0', + 'vlc2_Internal2_mac': '00:11:22:EF:AC:DF', + 'vlc_st_availability_zone': 'true', + 'fsb_volume_image_name_1': 'MME_FSB2_16ACP04_GA.qcow2', + 'sctp-b-ingress-src_subnet_prefix': '0.0.0.0', + 'sctp-a-ipv6-ingress_src_subnet_prefix_len': '0', + 'Internal1_allow_transit': 'true', + 'gpb_flavor_name': 'nv.c20r64d1', + 'availability_zone_max_count': '1', + 'fsb_volume_image_name_0': 'MME_FSB1_16ACP04_GA.qcow2', + 'sctp-b-ipv6-ingress_dst_addresses': 'local', + 'sctp-b-ipv6-egress_dst_subnet_prefix': '0.0.0.0', + 'sctp-b-ipv6-ingress_ethertype': 'IPv4', + 'vlc1_Internal2_mac': '00:11:22:EF:AC:DF', + 'sctp-a-ingress-src_subnet_prefix': '0.0.0.0', + 'sctp-a-ipv6-ingress_action': 'pass', + 'Internal1_rpf': 'disable', + 'sctp-b-ingress_ethertype': 'IPv4', + 'sctp-b-egress_rule_application': 'any', + 'sctp-b-ingress-src_end_port': '65535.0', + 'sctp-a-ipv6-ingress_rule_protocol': 'any', + 'sctp-a-ingress-src_start_port': '0.0', + 'sctp-b-egress-dst_end_port': '65535.0' + }, + 'type': 'VF', + 'modelCustomizationName': 'VF_vMee 0', + 'vfModules': { + 'vf_vmee0..VfVmee..vmme_vlc..module-1': { + 'uuid': '522159d5-d6e0-4c2a-aa44-5a542a12a830', + 'invariantUuid': '98a7c88b-b577-476a-90e4-e25a5871e02b', + 'customizationUuid': '55b1be94-671a-403e-a26c-667e9c47d091', + 'description': null, + 'name': 'VfVmee..vmme_vlc..module-1', + 'version': '2', + 'modelCustomizationName': 'VfVmee..vmme_vlc..module-1', + 'properties': {'minCountInstances': 0, 'maxCountInstances': null, 'initialCount': 0}, + 'commands': {}, + 'volumeGroupAllowed': false + }, + 'vf_vmee0..VfVmee..vmme_gpb..module-2': { + 'uuid': '41708296-e443-4c71-953f-d9a010f059e1', + 'invariantUuid': '1cca90b8-3490-495e-87da-3f3e4c57d5b9', + 'customizationUuid': '6add59e0-7fe1-4bc4-af48-f8812422ae7c', + 'description': null, + 'name': 'VfVmee..vmme_gpb..module-2', + 'version': '2', + 'modelCustomizationName': 'VfVmee..vmme_gpb..module-2', + 'properties': {'minCountInstances': 0, 'maxCountInstances': null, 'initialCount': 0}, + 'commands': {}, + 'volumeGroupAllowed': false + }, + 'vf_vmee0..VfVmee..base_vmme..module-0': { + 'uuid': 'a27f5cfc-7f12-4f99-af08-0af9c3885c87', + 'invariantUuid': 'a6f9e51a-2b35-416a-ae15-15e58d61f36d', + 'customizationUuid': 'f8c040f1-7e51-4a11-aca8-acf256cfd861', + 'description': null, + 'name': 'VfVmee..base_vmme..module-0', + 'version': '2', + 'modelCustomizationName': 'VfVmee..base_vmme..module-0', + 'properties': {'minCountInstances': 1, 'maxCountInstances': 1, 'initialCount': 1}, + 'commands': {}, + 'volumeGroupAllowed': true + } + }, + 'volumeGroups': { + 'vf_vmee0..VfVmee..base_vmme..module-0': { + 'uuid': 'a27f5cfc-7f12-4f99-af08-0af9c3885c87', + 'invariantUuid': 'a6f9e51a-2b35-416a-ae15-15e58d61f36d', + 'customizationUuid': 'f8c040f1-7e51-4a11-aca8-acf256cfd861', + 'description': null, + 'name': 'VfVmee..base_vmme..module-0', + 'version': '2', + 'modelCustomizationName': 'VfVmee..base_vmme..module-0', + 'properties': {'minCountInstances': 1, 'maxCountInstances': 1, 'initialCount': 1} + } + } + } + }, + 'networks': { + 'ExtVL 0': { + 'uuid': 'ddc3f20c-08b5-40fd-af72-c6d14636b986', + 'invariantUuid': '379f816b-a7aa-422f-be30-17114ff50b7c', + 'description': 'ECOMP generic virtual link (network) base type for all other service-level and global networks', + 'name': 'ExtVL', + 'version': '37.0', + 'customizationUuid': '94fdd893-4a36-4d70-b16a-ec29c54c184f', + 'inputs': {}, + 'commands': {}, + 'properties': { + 'network_assignments': '{is_external_network=false, ipv4_subnet_default_assignment={min_subnets_count=1}, ecomp_generated_network_assignment=false, ipv6_subnet_default_assignment={min_subnets_count=1}}', + 'exVL_naming': '{ecomp_generated_naming=true}', + 'network_flows': '{is_network_policy=false, is_bound_to_vpn=false}', + 'network_homing': '{ecomp_selected_instance_node_target=false}' + }, + 'type': 'VL', + 'modelCustomizationName': 'ExtVL 0' + } + }, + 'configurations': { + 'Port Mirroring Configuration By Policy 0': { + 'uuid': 'b4398538-e89d-4f13-b33d-ca323434ba50', + 'invariantUuid': '6ef0ca40-f366-4897-951f-abd65d25f6f7', + 'description': 'A port mirroring configuration by policy object', + 'name': 'Port Mirroring Configuration By Policy', + 'version': '27.0', + 'customizationUuid': '3c3b7b8d-8669-4b3b-8664-61970041fad2', + 'inputs': {}, + 'commands': {}, + 'properties': {}, + 'type': 'Configuration', + 'modelCustomizationName': 'Port Mirroring Configuration By Policy 0', + 'sourceNodes': [], + 'collectorNodes': null, + 'configurationByPolicy': false + } + }, + 'serviceProxies': {}, + 'vfModules': { + 'vf_vmee0..VfVmee..vmme_vlc..module-1': { + 'uuid': '522159d5-d6e0-4c2a-aa44-5a542a12a830', + 'invariantUuid': '98a7c88b-b577-476a-90e4-e25a5871e02b', + 'customizationUuid': '55b1be94-671a-403e-a26c-667e9c47d091', + 'description': null, + 'name': 'VfVmee..vmme_vlc..module-1', + 'version': '2', + 'modelCustomizationName': 'VfVmee..vmme_vlc..module-1', + 'properties': {'minCountInstances': 0, 'maxCountInstances': null, 'initialCount': 0}, + 'commands': {}, + 'volumeGroupAllowed': false + }, + 'vf_vmee0..VfVmee..vmme_gpb..module-2': { + 'uuid': '41708296-e443-4c71-953f-d9a010f059e1', + 'invariantUuid': '1cca90b8-3490-495e-87da-3f3e4c57d5b9', + 'customizationUuid': '6add59e0-7fe1-4bc4-af48-f8812422ae7c', + 'description': null, + 'name': 'VfVmee..vmme_gpb..module-2', + 'version': '2', + 'modelCustomizationName': 'VfVmee..vmme_gpb..module-2', + 'properties': {'minCountInstances': 0, 'maxCountInstances': null, 'initialCount': 0}, + 'commands': {}, + 'volumeGroupAllowed': false + }, + 'vf_vmee0..VfVmee..base_vmme..module-0': { + 'uuid': 'a27f5cfc-7f12-4f99-af08-0af9c3885c87', + 'invariantUuid': 'a6f9e51a-2b35-416a-ae15-15e58d61f36d', + 'customizationUuid': 'f8c040f1-7e51-4a11-aca8-acf256cfd861', + 'description': null, + 'name': 'VfVmee..base_vmme..module-0', + 'version': '2', + 'modelCustomizationName': 'VfVmee..base_vmme..module-0', + 'properties': {'minCountInstances': 1, 'maxCountInstances': 1, 'initialCount': 1}, + 'commands': {}, + 'volumeGroupAllowed': true + } + }, + 'volumeGroups': { + 'vf_vmee0..VfVmee..base_vmme..module-0': { + 'uuid': 'a27f5cfc-7f12-4f99-af08-0af9c3885c87', + 'invariantUuid': 'a6f9e51a-2b35-416a-ae15-15e58d61f36d', + 'customizationUuid': 'f8c040f1-7e51-4a11-aca8-acf256cfd861', + 'description': null, + 'name': 'VfVmee..base_vmme..module-0', + 'version': '2', + 'modelCustomizationName': 'VfVmee..base_vmme..module-0', + 'properties': {'minCountInstances': 1, 'maxCountInstances': 1, 'initialCount': 1} + } + }, + 'pnfs': {} + } + } + )); + } +}); diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.ts new file mode 100644 index 000000000..dc72f8f12 --- /dev/null +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.ts @@ -0,0 +1,76 @@ +import {Injectable} from '@angular/core'; +import {DefaultDataGeneratorService} from "../../../shared/services/defaultDataServiceGenerator/default.data.generator.service"; +import {NgRedux} from "@angular-redux/store"; +import {AppState} from "../../../shared/store/reducers"; +import {MessageBoxData} from "../../../shared/components/messageBox/messageBox.data"; +import {MessageBoxService} from "../../../shared/components/messageBox/messageBox.service"; +import * as _ from "lodash"; +import { SdcUiCommon} from "onap-ui-angular"; +import {SharedTreeService} from "../objectsToTree/shared.tree.service"; + +export class AvailableNodeIcons { + addIcon: boolean; + vIcon: boolean; + + constructor(addIcon: boolean, vIcon: boolean) { + this.addIcon = addIcon; + this.vIcon = vIcon; + } +} + +@Injectable() +export class AvailableModelsTreeService { + constructor(private _defaultDataGeneratorService: DefaultDataGeneratorService, + private store: NgRedux, + public _shareTreeService : SharedTreeService) { + } + + + + shouldOpenDialog(type: string, dynamicInputs: any, isEcompGeneratedNaming: boolean): boolean { + if (!isEcompGeneratedNaming || this._defaultDataGeneratorService.requiredFields[type].length > 0) { + return true; + } + + if (dynamicInputs) { + for(let input of dynamicInputs) { + if (input.isRequired && _.isEmpty(input.value)) { + return true; + } + } + } + return false; + } + + getOptionalVNFs(serviceUUID: string, vnfOriginalModelName : string) : any[] { + let result = []; + if(!_.isNil(this.store.getState().service.serviceInstance) && !_.isNil(this.store.getState().service.serviceInstance[serviceUUID])){ + const serviceVNFsInstances = this.store.getState().service.serviceInstance[serviceUUID].vnfs; + for(let vnfKey in serviceVNFsInstances){ + if(serviceVNFsInstances[vnfKey].originalName === vnfOriginalModelName){ + serviceVNFsInstances[vnfKey].vnfStoreKey = vnfKey; + result.push(serviceVNFsInstances[vnfKey]); + } + } + } + + + return result; + } + + + + addingAlertAddingNewVfModuleModal() : void { + let messageBoxData : MessageBoxData = new MessageBoxData( + "Select a parent", // modal title + "There are multiple instances on the right side that can contain this vf-module Please select the VNF instance, to add this vf-module to, on the right side and then click the + sign", + SdcUiCommon.ModalType.warning, + SdcUiCommon.ModalSize.medium, + [ + {text:"Close", size:"medium", closeModal:true} + ]); + + MessageBoxService.openModal.next(messageBoxData); + } + +} -- cgit 1.2.3-korg