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