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