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