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";
 
  12   GenericFormPopupComponent,
 
  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";
 
  23   deleteActionVfModuleInstance,
 
  25   pauseActionVFModuleInstance,
 
  26   removeVfModuleInstance,
 
  27   undoDeleteVfModuleInstance,
 
  29   updateVFModulePosition,
 
  31 } from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions";
 
  32 import {ComponentInfoService} from "../../../component-info/component-info.service";
 
  33 import {ComponentInfoType} from "../../../component-info/component-info-model";
 
  34 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
 
  35 import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
 
  36 import {FeatureFlagsService, Features} from "../../../../../shared/services/featureFlag/feature-flags.service";
 
  37 import {Utils} from "../../../../../shared/utils/utils";
 
  39 export class VFModuleModelInfo implements ILevelNodeInfo {
 
  40   constructor(private _dynamicInputsService: DynamicInputsService,
 
  41               private _sharedTreeService: SharedTreeService,
 
  42               private _dialogService: DialogService,
 
  43               private _vfModulePopupService: VfModulePopupService,
 
  44               private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
 
  45               private _iframeService: IframeService,
 
  46               private _featureFlagsService: FeatureFlagsService,
 
  47               private _store: NgRedux<AppState>,
 
  48               private _componentInfoService: ComponentInfoService) {
 
  51   name: string = 'vfModules';
 
  52   type: string = 'Module';
 
  53   typeName: string = 'M';
 
  54   componentInfoType = ComponentInfoType.VFMODULE;
 
  56   /***********************************************************
 
  57    * return if user should provide instance name or not.
 
  58    *        get info from parent (VNF)
 
  59    * @param currentModel - current Model object
 
  60    * @param parentModel - current parent Model object
 
  61    ************************************************************/
 
  62   isEcompGeneratedNaming(currentModel, parentModel): boolean {
 
  63     const ecompGeneratedNaming = !_.isNil(parentModel.properties) ? parentModel.properties.ecomp_generated_naming : undefined;
 
  64     return ecompGeneratedNaming === "true";
 
  67   /***********************************************************
 
  68    * return model dynamic inputs
 
  69    * @param currentModel - current Model object
 
  70    ************************************************************/
 
  71   updateDynamicInputsDataFromModel = (currentModel): any => {
 
  72     let displayInputs = _.isNil(currentModel) ? [] : currentModel.inputs;
 
  73     return _.isEmpty(displayInputs) ? [] : this._dynamicInputsService.getArbitraryInputs(displayInputs);
 
  76   /***********************************************************
 
  77    * return vfModule model
 
  78    * @param instanceModel - The model of the instance (usually extracted from
 
  79    *        serviceHierarchy store)
 
  80    ************************************************************/
 
  81   getModel = (instanceModel: any): Partial<VfModule> => {
 
  82     if (!_.isNil(instanceModel)) {
 
  83       return new VfModule(instanceModel, this._featureFlagsService.getAllFlags());
 
  88   createNode(instance: VfModuleInstance, currentModel: VfModule, parentModel: VNFModel, modelName: string, index: number, serviceModelId: string): VfModuleTreeNode {
 
  89     let dynamicModelName = Object.keys(instance)[index];
 
  90     instance = instance[Object.keys(instance)[index]];
 
  91     const isEcompGeneratedNaming: boolean = this.isEcompGeneratedNaming(currentModel, parentModel);
 
  93     const dynamicInputs = this.updateDynamicInputsDataFromModel(currentModel);
 
  94     let newVfModule: VfModuleTreeNode = new VfModuleTreeNode(instance, currentModel, modelName, dynamicInputs, isEcompGeneratedNaming, dynamicModelName);
 
  96     newVfModule.missingData = this._sharedTreeService.hasMissingData(instance, newVfModule.dynamicInputs, isEcompGeneratedNaming, []);
 
  97     newVfModule.typeName = this.typeName;
 
  98     newVfModule.menuActions = this.getMenuAction(<any>newVfModule, serviceModelId);
 
  99     newVfModule.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
 
 100     newVfModule.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
 
 101     newVfModule.pauseInstantiation = instance.pauseInstantiation;
 
 103     newVfModule = this._sharedTreeService.addingStatusProperty(newVfModule);
 
 107   createInstanceTreeNode(instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any {
 
 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, model, parentModel, storeKey, i, serviceModelId));
 
 116       return this.createNode(instance, model, parentModel, storeKey, 0, serviceModelId);
 
 120   /***********************************************************
 
 121    * return next level object (null because is last level)
 
 122    ************************************************************/
 
 123   getNextLevelObject(): any {
 
 127   getTooltip = (): string => 'VFmodule';
 
 129   getType = (): string => 'VFmodule';
 
 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, []);
 
 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);
 
 150       this._dialogService.addDialog(GenericFormPopupComponent, {
 
 151         type: PopupType.VF_MODULE,
 
 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
 
 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",
 
 171           {text: "Close", size: "medium", closeModal: true}
 
 173       MessageBoxService.openModal.next(messageBoxData);
 
 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);
 
 181     return keys.length === 1 ? this._store.getState().service.serviceInstance[serviceModelId].vnfs[keys[0]].vnfStoreKey : null;
 
 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();
 
 195         count += this.countNumberOfVFModule(vnfs[selectedVNF], node);
 
 197         for (let vnfKey in vnfs) {
 
 198           count += this.countNumberOfVFModule(vnfs[vnfKey], node);
 
 207   countNumberOfVFModule(vnf, node): number {
 
 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++;
 
 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);
 
 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();
 
 239       return this.showVFModuleOnSelectedVNF(node, selectedVNF, serviceModelId);
 
 241       const optionalSelected = this.getOptionalVNFs(serviceModelId, node.parent.data.modelUniqueId);
 
 242       if (optionalSelected.length === 1) {
 
 243         return this.showVFModuleOnSelectedVNF(node, optionalSelected[0].vnfStoreKey, serviceModelId);
 
 245         return new AvailableNodeIcons(false, false);
 
 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);
 
 259     return new AvailableNodeIcons(false, false);
 
 263   getOptionalVNFs(serviceUUID: string, vnfModelUniqueId: string): any[] {
 
 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]);
 
 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;
 
 286     const modelUuid = node.data.uuid;
 
 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') {
 
 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)
 
 311     if (_.isNil(maxInstances)) {
 
 315     return !(maxInstances > currentNodeCount);
 
 318   getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } {
 
 321         method: (node, serviceModelId) => {
 
 322           this._iframeService.addClassOpenModal('content');
 
 323           this._dialogService.addDialog(GenericFormPopupComponent, {
 
 324             type: PopupType.VF_MODULE,
 
 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
 
 338         visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
 
 339         enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
 
 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);
 
 346         visible: (node) => this._sharedTreeService.shouldShowAuditInfo(node),
 
 347         enable: (node) => this._sharedTreeService.shouldShowAuditInfo(node)
 
 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),
 
 355         method: (node, serviceModelId) => {
 
 356           this._store.dispatch(deleteActionVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName))
 
 358         visible: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId),
 
 359         enable: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId)
 
 362         method: (node, serviceModelId) => {
 
 363           this._store.dispatch(undoDeleteVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName));
 
 364           this._store.dispatch(deleteVFModuleField(node.data.modelName,  node.parent.data.vnfStoreKey, node.data.servicedId ,node.data.dynamicModelName, 'retainAssignments'));
 
 366         visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node),
 
 367         enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent, serviceModelId) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
 
 370         method: (node, serviceModelId) => {
 
 371           this.upgradeVFM(serviceModelId, node);
 
 373         visible: (node,serviceModelId) => {
 
 374           return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
 
 376         enable:  (node, serviceModelId) => {
 
 377           return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
 
 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));
 
 386           return this._sharedTreeService.shouldShowUndoUpgrade(node);
 
 389           return this._sharedTreeService.shouldShowUndoUpgrade(node);
 
 392       pauseInstantiation: {
 
 393         method: (node, serviceModelId) => {
 
 394           this._store.dispatch(pauseActionVFModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName));
 
 396         visible: () => this._sharedTreeService.shouldShowPauseInstantiation(),
 
 402   private upgradeVFM(serviceModelId, node) {
 
 403     if (FeatureFlagsService.getFlagState(Features.FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, this._store)) {
 
 404       this._iframeService.addClassOpenModal('content');
 
 405       this._dialogService.addDialog(GenericFormPopupComponent, {
 
 406         type: PopupType.VF_MODULE_UPGRADE,
 
 408           serviceId: serviceModelId,
 
 409           modelName: node.data.modelName,
 
 410           vFModuleStoreKey: node.data.dynamicModelName,
 
 411           vnfStoreKey: node.parent.data.vnfStoreKey,
 
 412           modelId: node.data.modelId,
 
 413           type: node.data.type,
 
 414           popupService: this._vfModuleUpgradePopupService,
 
 415           vfModule : _.cloneDeep(node)
 
 421       this._sharedTreeService.upgradeBottomUp(node, serviceModelId);
 
 422       this._store.dispatch(upgradeVFModule(node.data.modelName,  node.parent.data.vnfStoreKey, serviceModelId ,node.data.dynamicModelName));
 
 426   updatePosition(that, node, instanceId, parentStoreKey): void {
 
 427     that.store.dispatch(updateVFModulePosition(node, instanceId, parentStoreKey));
 
 431   getNodePosition(instance, deepDynamicName): number {
 
 432     return (!_.isNil(instance) && !_.isNil(instance[deepDynamicName])) ? instance[deepDynamicName].position : null;
 
 435   getInfo(model:Partial<VfModule>, instance): ModelInformationItem[] {
 
 436     const modelInformation = !_.isEmpty(model) ? [
 
 437       ModelInformationItem.createInstance("Base module", model.baseModule),
 
 438       ModelInformationItem.createInstance("Min instances", !_.isNull(model.min) ? String(model.min) : null),
 
 439       this._sharedTreeService.createMaximumToInstantiateModelInformationItem(model),
 
 440       ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.initial) ? String(model.initial) : null)
 
 443     const instanceInfo = [];
 
 444     const result = [modelInformation, instanceInfo];
 
 445     return _.uniq(_.flatten(result));