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 --- .../vnfGrouping/vnfGrouping.model.info.spec.ts | 291 +++++++++++++++++++++ .../models/vnfGrouping/vnfGrouping.model.info.ts | 272 +++++++++++++++++++ 2 files changed, 563 insertions(+) create mode 100644 vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.spec.ts create mode 100644 vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.ts (limited to 'vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping') diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.spec.ts new file mode 100644 index 000000000..532a8fe17 --- /dev/null +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.spec.ts @@ -0,0 +1,291 @@ + +import {HttpClientTestingModule, HttpTestingController} from "@angular/common/http/testing"; +import {getTestBed, TestBed} from "@angular/core/testing"; +import {MockNgRedux, NgReduxTestingModule} from "@angular-redux/store/testing"; +import {VnfGroupingModelInfo} from "./vnfGrouping.model.info"; +import {DynamicInputsService} from "../../dynamicInputs.service"; +import {SharedTreeService} from "../../shared.tree.service"; +import {VnfGroupPopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service"; +import {DialogService} from "ng2-bootstrap-modal"; +import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service"; +import {VnfGroupModel} from "../../../../../shared/models/vnfGroupModel"; +import {IframeService} from "../../../../../shared/utils/iframe.service"; +import {ActivatedRoute} from "@angular/router"; +import {RouterTestingModule} from "@angular/router/testing"; +import {DrawingBoardModes} from "../../../drawing-board.modes"; + +describe('VnfGroupingModelInfo Model Info', () => { + let injector; + let _dialogService : DialogService; + let _vnfGroupPopupService : VnfGroupPopupService; + let _dynamicInputsService : DynamicInputsService; + let _sharedTreeService : SharedTreeService; + let _iframeService : IframeService; + let vnfGroupModel: VnfGroupingModelInfo; + beforeAll(done => (async () => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule, NgReduxTestingModule, RouterTestingModule], + providers: [ + DialogService, + VnfGroupPopupService, + DynamicInputsService, + SharedTreeService, + IframeService, + MockNgRedux] + }); + await TestBed.compileComponents(); + injector = getTestBed(); + _sharedTreeService = injector.get(SharedTreeService); + + vnfGroupModel = new VnfGroupingModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vnfGroupPopupService, _iframeService, MockNgRedux.getInstance()); + })().then(done).catch(done.fail)); + + + test('VnfGroupingModelInfo should be defined', () => { + expect(vnfGroupModel).toBeDefined(); + }); + + test('VnfGroupingModelInfo should defined extra details', () => { + expect(vnfGroupModel.name).toEqual('vnfGroups'); + expect(vnfGroupModel.type).toEqual('VnfGroup'); + }); + + test('isEcompGeneratedNaming should return true if vnf group has isEcompGeneratedNaming is "true" ', () => { + let isEcompGeneratedNaming : boolean = vnfGroupModel.isEcompGeneratedNaming({ + properties: { + ecomp_generated_naming: 'true' + } + }); + expect(isEcompGeneratedNaming).toBeTruthy(); + }); + + + test('getTooltip should return "vnfGrouping"', () => { + let tooltip: string = vnfGroupModel.getTooltip(); + expect(tooltip).toEqual('VnfGroup'); + }); + + test('getType should return "vnfGrouping"', () => { + let tooltip: string = vnfGroupModel.getType(); + expect(tooltip).toEqual('VnfGroup'); + }); + + test('getNextLevelObject should return null', () => { + let nextLevel = vnfGroupModel.getNextLevelObject(); + expect(nextLevel).not.toBeNull(); + }); + + + test('showNodeIcons should return true if not reachLimit of max', ()=>{ + let serviceId : string = 'servicedId'; + let node = { + data : { + id : 'vnfGroupId', + name : 'vnfGroupName' + } + }; + jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({ + global:{ + drawingBoardStatus: "EDIT" + }, + service : { + serviceHierarchy : { + 'servicedId' : { + 'vnfGroups' : { + 'vnfGroupName' : { + 'properties' : { + } + } + } + } + }, + serviceInstance : { + 'servicedId' : { + 'existingVnfGroupCounterMap' : { + 'vnfGroupId' : 1 + }, + 'vnfGroups' : { + 'vnfGroupName' :{ + + } + } + } + } + } + }); + + let result = vnfGroupModel.showNodeIcons(node, serviceId); + expect(result).toEqual(new AvailableNodeIcons(true , false)); + }); + + test('getNodeCount should return number of nodes', ()=>{ + let serviceId : string = 'servicedId'; + jest.spyOn(_sharedTreeService, 'getExistingInstancesWithDeleteMode').mockReturnValue(0); + jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({ + global : {}, + service : { + serviceHierarchy : { + 'servicedId' : { + 'vnfGroups' : { + 'vnfGroupName' : { + 'properties' : { + } + } + } + } + }, + serviceInstance : { + 'servicedId' : { + 'existingVnfGroupCounterMap' : { + 'vnfGroupId' : 1 + }, + 'vnfGroups' : { + 'vnfGroupName' :{ + 'originalName' : 'vnfGroupName' + } + } + } + } + } + }); + + let node = { + data : { + id : 'vnfGroupId', + name : 'vnfGroupName', + modelUniqueId: 'vnfGroupId', + } + }; + let result = vnfGroupModel.getNodeCount(node , serviceId); + expect(result).toEqual(1); + + node.data.modelUniqueId = 'vnfGroupId_notExist'; + result = vnfGroupModel.getNodeCount(node , serviceId); + expect(result).toEqual(0); + + result = vnfGroupModel.getNodeCount(node , serviceId + '_notExist'); + expect(result).toEqual(0); + }); + + test('getModel should return VnfGroup model', () => { + let model: VnfGroupModel = vnfGroupModel.getModel('ResourceGroup0', { + originalName : 'ResourceGroup0' + }, getServiceHierarchy()); + expect(model.type).toEqual('VnfGroup'); + }); + + test('getMenuAction: showAuditInfoVnfGroup', ()=>{ + + jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({ + global: { + "drawingBoardStatus": DrawingBoardModes.RETRY + } + }); + jest.spyOn(_sharedTreeService, 'isRetryMode').mockReturnValue(true); + let node = { + data : { + "modelId": "6b528779-44a3-4472-bdff-9cd15ec93450", + "action": "Create", + "isFailed": true, + } + }; + let serviceModelId = "6b528779-44a3-4472-bdff-9cd15ec93450"; + let result = vnfGroupModel.getMenuAction(node, serviceModelId); + spyOn(result['showAuditInfo'], 'method'); + expect(result['showAuditInfo']).toBeDefined(); + expect(result['showAuditInfo'].visible(node)).toBeTruthy(); + expect(result['showAuditInfo'].enable(node)).toBeTruthy(); + result['showAuditInfo']['method'](node, serviceModelId); + expect(result['showAuditInfo']['method']).toHaveBeenCalledWith(node, serviceModelId); + }); + + function getServiceHierarchy(){ + return { + "service": { + "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450", + "invariantUuid": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", + "name": "action-data", + "version": "1.0", + "toscaModelURL": null, + "category": "", + "serviceType": "", + "serviceRole": "", + "description": "", + "serviceEcompNaming": "false", + "instantiationType": "Macro", + "inputs": { + "2017488_adiodvpe0_ASN": { + "type": "string", + "description": "AV/PE", + "entry_schema": null, + "inputProperties": null, + "constraints": [], + "required": true, + "default": "AV_vPE" + } + }, + "vidNotions": { + "instantiationUI": "legacy", + "modelCategory": "other" + } + }, + "vnfGroups": { + "ResourceGroup0": { + "type": "VnfGroup", + "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413", + "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d", + "version": "1", + "name": "ResourceGroup0", + "modelCustomizationName": "ResourceGroup0", + "properties": { + "contained_resource_type": "VF", + "role": "SERVICE-ACCESS", + "function": "DATA", + "description": "DDD0", + "type": "LOAD-GROUP" + }, + "members": { + "vdbe_svc_vprs_proxy 0": { + "uuid": "65fadfa8-a0d9-443f-95ad-836cd044e26c", + "invariantUuid": "f4baae0c-b3a5-4ca1-a777-afbffe7010bc", + "description": "A Proxy for Service vDBE_Svc_vPRS", + "name": "vDBE_Svc_vPRS Service Proxy", + "version": "1.0", + "customizationUuid": "bdb63d23-e132-4ce7-af2c-a493b4cafac9", + "inputs": {}, + "commands": {}, + "properties": {}, + "type": "Service Proxy", + "sourceModelUuid": "da7827a2-366d-4be6-8c68-a69153c61274", + "sourceModelInvariant": "24632e6b-584b-4f45-80d4-fefd75fd9f14", + "sourceModelName": "vDBE_Svc_vPRS" + }, + "vdbe_svc_vprs_proxy 1": { + "uuid": "111dfa8-a0d9-443f-95ad-836cd044e26c", + "invariantUuid": "111ae0c-b3a5-4ca1-a777-afbffe7010bc", + "description": "A Proxy for Service vDBE_Svc_vPRS", + "name": "111_Svc_vPRS Service Proxy", + "version": "1.0", + "customizationUuid": "1113d23-e132-4ce7-af2c-a493b4cafac9", + "inputs": {}, + "commands": {}, + "properties": {}, + "type": "Service Proxy", + "sourceModelUuid": "11127a2-366d-4be6-8c68-a69153c61274", + "sourceModelInvariant": "1112e6b-584b-4f45-80d4-fefd75fd9f14", + "sourceModelName": "111_Svc_vPRS" + } + } + } + }, + "networks": {}, + "collectionResource": {}, + "configurations": {}, + "fabricConfigurations": {}, + "serviceProxies": {}, + "vfModules": {}, + "volumeGroups": {}, + "pnfs": {} + } + } +}); diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.ts new file mode 100644 index 000000000..7f2052a0c --- /dev/null +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.ts @@ -0,0 +1,272 @@ +import {ILevelNodeInfo} from "../basic.model.info"; +import {DynamicInputsService} from "../../dynamicInputs.service"; +import {ITreeNode} from "angular-tree-component/dist/defs/api"; +import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service"; +import {VnfGroupModel} from "../../../../../shared/models/vnfGroupModel"; +import {VnfGroupTreeNode} from "../../../../../shared/models/vnfGroupTreeNode"; +import {SharedTreeService} from "../../shared.tree.service"; +import {VnfGroupPopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service"; +import { + GenericFormPopupComponent, + PopupType +} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component"; +import {DialogService} from 'ng2-bootstrap-modal'; +import {AppState} from "../../../../../shared/store/reducers"; +import {NgRedux} from "@angular-redux/store"; +import {changeInstanceCounter, removeInstance} from "../../../../../shared/storeUtil/utils/general/general.actions"; +import {IframeService} from "../../../../../shared/utils/iframe.service"; +import { + deleteActionVnfGroupInstance, + undoDeleteActionVnfGroupInstance +} from "../../../../../shared/storeUtil/utils/vnfGroup/vnfGroup.actions"; +import {RelatedVnfMemberInfoModel} from "../relatedVnfMember/relatedVnfMember.info.model"; +import {SearchMembersModalComponent} from "../../../../../shared/components/searchMembersModal/search-members-modal.component"; +import * as _ from "lodash"; +import {MessageBoxData} from "../../../../../shared/components/messageBox/messageBox.data"; +import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service"; + +export class VnfGroupingModelInfo implements ILevelNodeInfo { + constructor(private _dynamicInputsService: DynamicInputsService, + private _sharedTreeService: SharedTreeService, + private _dialogService: DialogService, + private _vnfGroupPopupService: VnfGroupPopupService, + private _iframeService: IframeService, + private _store: NgRedux) { + } + + name: string = 'vnfGroups'; + type: string = 'VnfGroup'; + typeName: string = 'G'; + childType: string = 'RelatedVnfMemberInfoModel'; + childName: string = 'vnfs'; + limitMembers : number; + + /*********************************************************** + * return if user should provide instance name or not. + * get info from parent (VNF) + * @param currentModel - current Model object + ************************************************************/ + isEcompGeneratedNaming(currentModel): boolean { + const ecompGeneratedNaming = currentModel.properties.ecomp_generated_naming; + return ecompGeneratedNaming === "true"; + } + + /*********************************************************** + * return model dynamic inputs + * @param currentModel - current Model object + ************************************************************/ + updateDynamicInputsDataFromModel = (currentModel): any => { + let displayInputs = currentModel.inputs; + return _.isEmpty(displayInputs) ? [] : this._dynamicInputsService.getArbitraryInputs(displayInputs); + }; + + /*********************************************************** + * return next level object (null because is last level) + ************************************************************/ + getNextLevelObject = (): RelatedVnfMemberInfoModel => { + return new RelatedVnfMemberInfoModel(this._sharedTreeService, this._dynamicInputsService, this._store); + }; + + getTooltip = (): string => 'VnfGroup'; + + getType = (): string => 'VnfGroup'; + + createInstanceTreeNode(instance: any, model: any, parentModel: any, storeKey: string): any { + let node = new VnfGroupTreeNode(instance, model, storeKey); + node.missingData = this.hasMissingData(instance, node, model.isEcompGeneratedNaming); + node = this._sharedTreeService.addingStatusProperty(node); + node.typeName = this.typeName; + node.menuActions = this.getMenuAction(node, model.uuid); + node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed; + node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage: ""; + node.limitMembers = (!_.isNil(model.properties.quantity)) ? model.properties.quantity : null; + return node; + } + + getModel(modelId: string, instance: any, serviceHierarchy): any { + const originalModelName = instance.originalName ? instance.originalName : modelId; + return new VnfGroupModel(serviceHierarchy[this.name][originalModelName]); + } + + hasMissingData(instance, dynamicInputs: any, isEcompGeneratedNaming: boolean): boolean { + return this._sharedTreeService.hasMissingData(instance, dynamicInputs, isEcompGeneratedNaming, []); + } + + onClickAdd(node: ITreeNode, serviceModelId: string): void { + this._dialogService.addDialog(GenericFormPopupComponent, { + type: PopupType.VNF_GROUP, + uuidData: { + serviceId: serviceModelId, + modelName: node.data.name, + vnfGroupStoreKey: null, + modelId: node.data.modelVersionId, + type: node.data.type, + popupService: this._vnfGroupPopupService + }, + node: node, + isUpdateMode: false + }); + } + + getNodeCount(node: ITreeNode, serviceModelId: string): number { + let map = null; + if (!_.isNil(this._store.getState().service.serviceInstance[serviceModelId])) { + map = this._store.getState().service.serviceInstance[serviceModelId].existingVnfGroupCounterMap || 0; + if (!_.isNil(map)) { + let count = map[node.data.modelUniqueId] || 0; + count -= this._sharedTreeService.getExistingInstancesWithDeleteMode(node, serviceModelId, 'vnfGroups'); + return count; + } + } + return 0; + } + + /*********************************************************** + * should show node icon + * @param node - current ITrees node + * @param serviceModelId - service id + ************************************************************/ + showNodeIcons(node: ITreeNode, serviceModelId: string): AvailableNodeIcons { + const showAddIcon = this._sharedTreeService.shouldShowAddIcon(); + return new AvailableNodeIcons(showAddIcon, false); + } + + getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } { + return { + edit: { + method: (node, serviceModelId) => { + this._iframeService.addClassOpenModal('content'); + this._dialogService.addDialog(GenericFormPopupComponent, { + type: PopupType.VNF_GROUP, + uuidData: { + serviceId: serviceModelId, + modelName: node.data.modelName, + vnfGroupStoreKey: node.data.vnfGroupStoreKey, + modelId: node.data.modelId, + type: node.data.type, + popupService: this._vnfGroupPopupService + }, + node: node, + isUpdateMode: true + }); + }, + visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node), + enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node) + }, + remove: { + method: (node, serviceModelId) => { + if ((!_.isNil(node.data.children) && node.data.children.length === 0) || _.isNil(node.data.children)) { + let storeKey: string = node.data.vnfGroupStoreKey; + this._store.dispatch(removeInstance(node.data.vnfGroupStoreKey, serviceModelId, storeKey, node)); + this._store.dispatch(changeInstanceCounter(node.data.modelUniqueId, serviceModelId, -1, node)); + this._sharedTreeService.selectedVNF = null; + } else { + let messageBoxData: MessageBoxData = new MessageBoxData( + "Remove VNFGroup", // modal title + "You are about to remove this group and all its children from this service. Are you sure you want to remove it?", + "warning", + "md", + [ + { + text: "Remove Group", + size: "large", + callback: this.removeGroup.bind(this, node, serviceModelId), + closeModal: true + }, + {text: "Don’t Remove", size: "medium", closeModal: true} + ]); + + MessageBoxService.openModal.next(messageBoxData); + } + }, + visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node), + enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node) + }, + addGroupMember: { + method: (node, serviceModelId) => { + let serviceHierarchy = this._store.getState().service.serviceHierarchy[serviceModelId]; + let serviceInstance = this._store.getState().service.serviceInstance[serviceModelId]; + let vnfGroupModel = new VnfGroupModel(serviceHierarchy['vnfGroups'][node.data.modelName]); + this._dialogService.addDialog(SearchMembersModalComponent, { + title: 'Add members to group', + description: 'Select VNF instances to associate', + subscriberId: serviceInstance.globalSubscriberId, + serviceType: serviceInstance.subscriptionServiceType, + vnfGroupModel: vnfGroupModel, + serviceModelId: serviceModelId, + node: node.data, + searchFields: [{ + title: 'Service model name', + dataTestId: 'sourceModelName', + value: (Object.values(vnfGroupModel.members))[0].sourceModelName + }, + { + title: 'Service invariant UUID', + dataTestId: 'sourceModelInvariant', + value: (Object.values(vnfGroupModel.members))[0].sourceModelInvariant + }] + } + ); + }, + visible: (node) => !_.isNil(node.data.action) ? node.data.action.split('_').pop() !== 'Delete' : true, + enable: (node) => !_.isNil(node.data.action) ? node.data.action.split('_').pop() !== 'Delete' : true + }, + showAuditInfo: { + method: (node, serviceModelId) => { + let instance = this._store.getState().service.serviceInstance[serviceModelId].vnfGroups[node.data.vnfGroupStoreKey]; + this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VNFGROUP', this); + }, + visible: (node) => this._sharedTreeService.shouldShowAuditInfo(node), + enable: (node) => this._sharedTreeService.shouldShowAuditInfo(node) + }, + delete: { + method: (node, serviceModelId) => { + if ((!_.isNil(node.data.children) && node.data.children.length === 0) || _.isNil(node.data.children)) { + this._store.dispatch(deleteActionVnfGroupInstance(node.data.vnfGroupStoreKey, serviceModelId)); + }else { + this._sharedTreeService.shouldShowDeleteInstanceWithChildrenModal(node, serviceModelId, (node, serviceModelId)=>{ + this._sharedTreeService.removeDeleteAllChild(node, serviceModelId, (node, serviceModelId)=>{ + this._store.dispatch(deleteActionVnfGroupInstance(node.data.vnfGroupStoreKey, serviceModelId)); + }); + }); + } + }, + visible: (node) => this._sharedTreeService.shouldShowDelete(node), + enable: (node) => this._sharedTreeService.shouldShowDelete(node) + }, + undoDelete: { + method: (node, serviceModelId) => { + if ((!_.isNil(node.data.children) && node.data.children.length === 0) || _.isNil(node.data.children)) { + this._store.dispatch(undoDeleteActionVnfGroupInstance(node.data.vnfGroupStoreKey, serviceModelId)); + } else { + this._sharedTreeService.undoDeleteAllChild(node, serviceModelId, (node, serviceModelId) => { + this._store.dispatch(undoDeleteActionVnfGroupInstance(node.data.vnfGroupStoreKey, serviceModelId)); + }); + } + }, + visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node), + enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId) + } + }; + + + } + + removeGroup(this, node, serviceModelId) { + this._store.dispatch(removeInstance(node.data.modelName, serviceModelId, node.data.vnfGroupStoreKey, node)); + this._store.dispatch(changeInstanceCounter(node.data.modelUniqueId, serviceModelId, -1, node)); + this._sharedTreeService.selectedVNF = null; + } + + updatePosition(that , node, instanceId): void { + // TODO + } + + getNodePosition(instance): number { + return !_.isNil(instance) ? instance.position : null; + } + + onSelectedNode(node: ITreeNode): void { + } + +} -- cgit 1.2.3-korg