Adding unlimited max value to VNF, NETWORK
[vid.git] / vid-webpack-master / src / app / drawingBoard / service-planning / objectsToTree / models / vfModule / vfModule.model.info.ts
1 import {DynamicInputsService} from "../../dynamicInputs.service";
2 import {ILevelNodeInfo} from "../basic.model.info";
3 import * as _ from "lodash";
4 import {VNFModel} from "../../../../../shared/models/vnfModel";
5 import {SharedTreeService} from "../../shared.tree.service";
6 import {VfModuleTreeNode} from "../../../../../shared/models/vfModuleTreeNode";
7 import {VfModuleInstance} from "../../../../../shared/models/vfModuleInstance";
8 import {VfModule} from "../../../../../shared/models/vfModule";
9 import {NgRedux} from "@angular-redux/store";
10 import {ITreeNode} from "angular-tree-component/dist/defs/api";
11 import {
12   GenericFormPopupComponent,
13   PopupType
14 } from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
15 import {DialogService} from "ng2-bootstrap-modal";
16 import {VfModulePopuopService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service";
17 import {AppState} from "../../../../../shared/store/reducers";
18 import {MessageBoxData} from "../../../../../shared/components/messageBox/messageBox.data";
19 import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service";
20 import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service";
21 import {IframeService} from "../../../../../shared/utils/iframe.service";
22 import {
23   deleteActionVfModuleInstance, deleteVFModuleField,
24   removeVfModuleInstance,
25   undoDeleteVfModuleInstance,
26   undoUgradeVFModule, updateVFModuleField,
27   updateVFModulePosition,
28   upgradeVFModule
29 } from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions";
30 import {ComponentInfoService} from "../../../component-info/component-info.service";
31 import {ComponentInfoType} from "../../../component-info/component-info-model";
32 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
33 import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
34 import {FeatureFlagsService, Features} from "../../../../../shared/services/featureFlag/feature-flags.service";
35
36 export class VFModuleModelInfo implements ILevelNodeInfo {
37   constructor(private _dynamicInputsService: DynamicInputsService,
38               private _sharedTreeService: SharedTreeService,
39               private _dialogService: DialogService,
40               private _vfModulePopupService: VfModulePopuopService,
41               private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
42               private _iframeService: IframeService,
43               private _featureFlagsService: FeatureFlagsService,
44               private _store: NgRedux<AppState>,
45               private _componentInfoService: ComponentInfoService) {
46   }
47
48   name: string = 'vfModules';
49   type: string = 'Module';
50   typeName: string = 'M';
51   componentInfoType = ComponentInfoType.VFMODULE;
52
53   /***********************************************************
54    * return if user should provide instance name or not.
55    *        get info from parent (VNF)
56    * @param currentModel - current Model object
57    * @param parentModel - current parent Model object
58    ************************************************************/
59   isEcompGeneratedNaming(currentModel, parentModel): boolean {
60     const ecompGeneratedNaming = !_.isNil(parentModel.properties) ? parentModel.properties.ecomp_generated_naming : undefined;
61     return ecompGeneratedNaming === "true";
62   }
63
64   /***********************************************************
65    * return model dynamic inputs
66    * @param currentModel - current Model object
67    ************************************************************/
68   updateDynamicInputsDataFromModel = (currentModel): any => {
69     let displayInputs = _.isNil(currentModel) ? [] : currentModel.inputs;
70     return _.isEmpty(displayInputs) ? [] : this._dynamicInputsService.getArbitraryInputs(displayInputs);
71   };
72
73   /***********************************************************
74    * return vfModule model
75    * @param vfModuleModelId - current Model id
76    * @param instance
77    * @param serviceHierarchy - serviceHierarchy
78    ************************************************************/
79   getModel = (vfModuleModelId: string, instance, serviceHierarchy): any => {
80     if (!_.isNil(serviceHierarchy)) {
81       if (!_.isNil(serviceHierarchy[this.name]) && !_.isNil(serviceHierarchy[this.name][vfModuleModelId])) {
82         return serviceHierarchy[this.name][vfModuleModelId];
83       }
84     }
85     return {};
86   };
87
88   createNode(instance: VfModuleInstance, currentModel: VfModule, parentModel: VNFModel, modelName: string, index: number): VfModuleTreeNode {
89     let dynamicModelName = Object.keys(instance)[index];
90     instance = instance[Object.keys(instance)[index]];
91     const isEcompGeneratedNaming: boolean = this.isEcompGeneratedNaming(currentModel, parentModel);
92
93     const dynamicInputs = this.updateDynamicInputsDataFromModel(currentModel);
94     let newVfModule: VfModuleTreeNode = new VfModuleTreeNode(instance, currentModel, modelName, dynamicInputs, isEcompGeneratedNaming, dynamicModelName);
95
96     newVfModule.missingData = this._sharedTreeService.hasMissingData(instance, newVfModule.dynamicInputs, isEcompGeneratedNaming, []);
97     newVfModule.typeName = this.typeName;
98     newVfModule.menuActions = this.getMenuAction(<any>newVfModule, currentModel.uuid);
99     newVfModule.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
100     newVfModule.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
101
102     newVfModule = this._sharedTreeService.addingStatusProperty(newVfModule);
103     return newVfModule;
104   }
105
106   createInstanceTreeNode(instance: VfModuleInstance, currentModel: VfModule, parentModel: VNFModel, modelName: string): VfModuleTreeNode | VfModuleTreeNode[] {
107     let numberOfChilds = Object.keys(instance).length;
108     if (numberOfChilds > 1) {
109       let result: VfModuleTreeNode[] = [];
110       for (let i = 0; i < numberOfChilds; i++) {
111         result.push(this.createNode(instance, currentModel, parentModel, modelName, i));
112       }
113       return result;
114     } else {
115       return this.createNode(instance, currentModel, parentModel, modelName, 0);
116     }
117   }
118
119   /***********************************************************
120    * return next level object (null because is last level)
121    ************************************************************/
122   getNextLevelObject(): any {
123     return null;
124   }
125
126   getTooltip = (): string => 'VFmodule';
127
128   getType = (): string => 'VFmodule';
129
130   /***********************************************************
131    * return if instance has missing data
132    * @param instance - vnf instance
133    * @param dynamicInputs
134    * @param isEcompGeneratedNaming
135    ************************************************************/
136   hasMissingData(instance, dynamicInputs: any, isEcompGeneratedNaming: boolean): boolean {
137     return this._sharedTreeService.hasMissingData(instance, dynamicInputs, isEcompGeneratedNaming, []);
138   }
139
140
141   /***********************************************************
142    * return if instance has missing data
143    * @param node - VFModule node
144    * @param serviceModelId - current service id
145    ************************************************************/
146   onClickAdd(node: ITreeNode, serviceModelId: string): void {
147     const vnfStoreKey = this._sharedTreeService.getSelectedVNF() || this.getDefaultVNF(node.parent, serviceModelId);
148     if (vnfStoreKey) {
149       this._dialogService.addDialog(GenericFormPopupComponent, {
150         type: PopupType.VF_MODULE,
151         uuidData: <any>{
152           serviceId: serviceModelId,
153           modelName: node.data.name,
154           vFModuleStoreKey: null,
155           vnfStoreKey: vnfStoreKey,
156           modelId: node.data.modelId,
157           type: node.data.type,
158           popupService: this._vfModulePopupService
159         },
160         node: node,
161         isUpdateMode: false
162       });
163     } else {
164       let messageBoxData: MessageBoxData = new MessageBoxData(
165         "Select a parent",  // modal title
166         "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",
167         <any>"warning",
168         <any>"md",
169         [
170           {text: "Close", size: "medium", closeModal: true}
171         ]);
172       MessageBoxService.openModal.next(messageBoxData);
173     }
174   }
175
176   getDefaultVNF(node: ITreeNode, serviceModelId: string): string {
177     let keys = _.keys(_.pickBy(this._store.getState().service.serviceInstance[serviceModelId].vnfs, vnf => {
178       return (vnf.originalName == node.data.name);
179     }));
180     return keys.length === 1 ? this._store.getState().service.serviceInstance[serviceModelId].vnfs[keys[0]].vnfStoreKey : null;
181   }
182
183   /***********************************************************
184    * return number of existing instances (in all VNF's)
185    * @param node - VfModule node
186    * @param serviceModelId - current service id
187    ************************************************************/
188   getNodeCount(node: ITreeNode, serviceModelId: string): number {
189     let count: number = 0;
190     if (!_.isNil(this._store.getState().service.serviceInstance) && !_.isNil(this._store.getState().service.serviceInstance[serviceModelId])) {
191       const vnfs = this._store.getState().service.serviceInstance[serviceModelId].vnfs;
192
193       for (let vnfKey in vnfs) {
194         count += this.countNumberOfVFModule(vnfs[vnfKey], node);
195       }
196       return count;
197     }
198     return count;
199   }
200
201
202   countNumberOfVFModule(vnf, node): number {
203     let count = 0;
204     for (let vfModuleKey in vnf['vfModules']) {
205       for (let vfModule in vnf['vfModules'][vfModuleKey]) {
206         if (vnf['vfModules'][vfModuleKey][vfModule]['modelInfo'].modelCustomizationId === node.data.modelUniqueId) {
207           const vfModuleObj = vnf['vfModules'][vfModuleKey][vfModule];
208           if (!(!_.isNil(vfModuleObj) && !_.isNil(vfModuleObj.action) && vfModuleObj.action.split('_').pop() === 'Delete')) count++;
209         }
210       }
211     }
212     return count;
213   }
214
215   getCountVFModuleOfSelectedVNF(node: ITreeNode, vnfStoreKey: string, serviceModelId: string): number {
216     let count: number = 0;
217     if (!_.isNil(this._store.getState().service.serviceInstance) && !_.isNil(this._store.getState().service.serviceInstance[serviceModelId])) {
218       const vnfs = this._store.getState().service.serviceInstance[serviceModelId].vnfs;
219
220       for (let vnfKey in vnfs) {
221         count += this.countNumberOfVFModule(vnfs[vnfKey], node);
222       }
223       return count;
224     }
225     return count;
226   }
227
228
229   /***********************************************************
230    * should show node icon
231    * @param node - current ITrees node
232    * @param serviceModelId - service id
233    ************************************************************/
234   showNodeIcons(node: ITreeNode, serviceModelId: string): AvailableNodeIcons {
235     const selectedVNF: string = this._sharedTreeService.getSelectedVNF();
236     if (selectedVNF) {
237       return this.showVFModuleOnSelectedVNF(node, selectedVNF, serviceModelId);
238     } else {
239       const optionalSelected = this.getOptionalVNFs(serviceModelId, node.parent.data.name);
240       if (optionalSelected.length === 1) {
241         return this.showVFModuleOnSelectedVNF(node, optionalSelected[0].vnfStoreKey, serviceModelId);
242       } else {
243         return new AvailableNodeIcons(false, false);
244       }
245     }
246   }
247
248
249   showVFModuleOnSelectedVNF(node: ITreeNode, selectedVNF: string, serviceModelId: string): AvailableNodeIcons {
250
251     if (!_.isNil(this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF]) && node.parent.data.name === this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF].originalName) {
252       const existingVFModules = this.getCountVFModuleOfSelectedVNF(node, selectedVNF, serviceModelId);
253       const reachedLimit = this.isVFModuleReachedLimit(node, this._store.getState().service.serviceHierarchy, serviceModelId, existingVFModules);
254       const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !reachedLimit;
255       return new AvailableNodeIcons(showAddIcon, reachedLimit);
256     }
257     return new AvailableNodeIcons(false, false);
258
259   }
260
261   getOptionalVNFs(serviceUUID: string, vnfOriginalModelName: string): any[] {
262     let result = [];
263     if (!_.isNil(this._store.getState().service.serviceInstance) && !_.isNil(this._store.getState().service.serviceInstance[serviceUUID])) {
264       const serviceVNFsInstances = this._store.getState().service.serviceInstance[serviceUUID].vnfs;
265       for (let vnfKey in serviceVNFsInstances) {
266         if (serviceVNFsInstances[vnfKey].originalName === vnfOriginalModelName) {
267           serviceVNFsInstances[vnfKey].vnfStoreKey = vnfKey;
268           result.push(serviceVNFsInstances[vnfKey]);
269         }
270       }
271     }
272     return result;
273   }
274
275
276   /************************************************
277    return number of instances with action Delete
278    @type: vnfs networks, vngGroups (only vfModule)
279    @node : node model from the left tree
280    ************************************************/
281   getExistingInstancesWithDeleteMode(node, serviceModelId: string, selectedVNF: string): number {
282     const existingInstances = this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF].vfModules;
283     let counter = 0;
284     const modelUuid = node.data.uuid;
285
286     if (!_.isNil(existingInstances)) {
287       for (let instanceKey in existingInstances) {
288         let size = Object.keys(existingInstances[instanceKey]).length;
289         for (let i = 0; i < size; i++) {
290           let vfModuleDynamicKey = Object.keys(existingInstances[instanceKey])[i];
291           if (!_.isNil(existingInstances[instanceKey][vfModuleDynamicKey].action)) {
292             if (existingInstances[instanceKey][vfModuleDynamicKey]['uuid'] === modelUuid && existingInstances[instanceKey][vfModuleDynamicKey].action.split('_').pop() === 'Delete') {
293               counter++;
294             }
295           }
296         }
297
298       }
299     }
300     return counter;
301   }
302
303   isVFModuleReachedLimit(node: any, serviceHierarchy: any, serviceModelId: string, currentNodeCount: number): boolean {
304     let maxNodes: number = 1;
305     let vnfModules = serviceHierarchy[serviceModelId].vfModules;
306     if (vnfModules[node.data.name]) {
307       maxNodes = vnfModules[node.data.name].properties.maxCountInstances || 1;
308     }
309     return !(maxNodes > currentNodeCount);
310   }
311
312   getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } {
313     return {
314       edit: {
315         method: (node, serviceModelId) => {
316           this._iframeService.addClassOpenModal('content');
317           this._dialogService.addDialog(GenericFormPopupComponent, {
318             type: PopupType.VF_MODULE,
319             uuidData: <any>{
320               serviceId: serviceModelId,
321               modelName: node.data.modelName,
322               vFModuleStoreKey: node.data.dynamicModelName,
323               vnfStoreKey: node.parent.data.vnfStoreKey,
324               modelId: node.data.modelId,
325               type: node.data.type,
326               popupService: this._vfModulePopupService
327             },
328             node: node,
329             isUpdateMode: true
330           });
331         },
332         visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
333         enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
334       },
335       showAuditInfo: {
336         method: (node, serviceModelId) => {
337           let instance = this._store.getState().service.serviceInstance[serviceModelId].vnfs[node.parent.data.vnfStoreKey].vfModules[node.data.modelName][node.data.modelVersionId];
338           this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VFMODULE', this);
339         },
340         visible: (node) => this._sharedTreeService.shouldShowAuditInfo(node),
341         enable: (node) => this._sharedTreeService.shouldShowAuditInfo(node)
342       },
343       remove: {
344         method: (node, serviceModelId) => this._store.dispatch(removeVfModuleInstance(node.data.modelName, serviceModelId, node.parent.data.modelName, node.parent.data.vnfStoreKey, node.data.dynamicModelName)),
345         visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
346         enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
347       },
348       delete: {
349         method: (node, serviceModelId) => {
350           this._store.dispatch(deleteActionVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId))
351         },
352         visible: (node) => this._sharedTreeService.shouldShowDelete(node),
353         enable: (node) => this._sharedTreeService.shouldShowDelete(node)
354       },
355       undoDelete: {
356         method: (node, serviceModelId) => {
357           this._store.dispatch(undoDeleteVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId));
358           this._store.dispatch(deleteVFModuleField(node.data.modelName,  node.parent.data.vnfStoreKey, node.data.servicedId ,node.data.dynamicModelName, 'retainAssignments'));
359         },
360         visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node),
361         enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
362       },
363       upgrade: {
364         method: (node, serviceModelId) => {
365           this.upgradeVFM(serviceModelId, node);
366         },
367         visible: (node,serviceModelId) => {
368           return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
369         },
370         enable:  (node, serviceModelId) => {
371           return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
372         }
373       },
374       undoUpgrade: {
375         method: (node, serviceModelId) => {
376           this._sharedTreeService.undoUpgradeBottomUp(node, serviceModelId);
377           this._store.dispatch(undoUgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName));
378         },
379         visible: (node) => {
380           return this._sharedTreeService.shouldShowUndoUpgrade(node);
381         },
382         enable: (node) => {
383           return this._sharedTreeService.shouldShowUndoUpgrade(node);
384         }
385       },
386     };
387   }
388
389   private upgradeVFM(serviceModelId, node) {
390     if (FeatureFlagsService.getFlagState(Features.FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, this._store)) {
391       this._iframeService.addClassOpenModal('content');
392       this._dialogService.addDialog(GenericFormPopupComponent, {
393         type: PopupType.VF_MODULE_UPGRADE,
394         uuidData: <any>{
395           serviceId: serviceModelId,
396           modelName: node.data.modelName,
397           vFModuleStoreKey: node.data.dynamicModelName,
398           vnfStoreKey: node.parent.data.vnfStoreKey,
399           modelId: node.data.modelId,
400           type: node.data.type,
401           popupService: this._vfModuleUpgradePopupService,
402           vfModule : _.cloneDeep(node)
403         },
404         node,
405         isUpdateMode: false
406       });
407     }else {
408       this._sharedTreeService.upgradeBottomUp(node, serviceModelId);
409       this._store.dispatch(upgradeVFModule(node.data.modelName,  node.parent.data.vnfStoreKey, serviceModelId ,node.data.dynamicModelName));
410     }
411   }
412
413   updatePosition(that, node, instanceId, parentStoreKey): void {
414     that.store.dispatch(updateVFModulePosition(node, instanceId, parentStoreKey));
415   }
416
417
418   getNodePosition(instance, deepDynamicName): number {
419     return (!_.isNil(instance) && !_.isNil(instance[deepDynamicName])) ? instance[deepDynamicName].position : null;
420   }
421
422   getInfo(model, instance): ModelInformationItem[] {
423     const modelInformation = !_.isEmpty(model) && !_.isEmpty(model.properties) ? [
424       ModelInformationItem.createInstance("Base module", model.properties.baseModule),
425       ModelInformationItem.createInstance("Min instances", !_.isNull(model.properties.minCountInstances) ? String(model.properties.minCountInstances) : null),
426       ModelInformationItem.createInstance("Max instances", !_.isNull(model.properties.maxCountInstances) ? String(model.properties.maxCountInstances) : null),
427       ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.properties.initialCount) ? String(model.properties.initialCount) : null)
428     ] : [];
429
430     const instanceInfo = [];
431     const result = [modelInformation, instanceInfo];
432     return _.uniq(_.flatten(result));
433   }
434 }