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