Adding unlimited max value to VNF, NETWORK 39/99339/6
authorYoav Schneiderman <yoav.schneiderman@intl.att.com>
Mon, 9 Dec 2019 14:42:21 +0000 (16:42 +0200)
committerYoav Schneiderman <yoav.schneiderman@intl.att.com>
Tue, 10 Dec 2019 18:08:09 +0000 (20:08 +0200)
Issue-ID: VID-726
Signed-off-by: Yoav Schneiderman <yoav.schneiderman@intl.att.com>
Change-Id: I0c3d503c8e4f6cb14081de8f6a619a67eee080b7
Signed-off-by: Yoav Schneiderman <yoav.schneiderman@intl.att.com>
22 files changed:
features.properties.md
vid-app-common/src/main/java/org/onap/vid/properties/Features.java
vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts
vid-webpack-master/cypress/integration/iFrames/viewOnlyDrawingBoard.e2e.ts
vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json
vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts
vid-webpack-master/src/app/shared/models/networkModel.ts
vid-webpack-master/src/app/shared/models/vnfModel.ts
vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts
vid-webpack-master/src/app/shared/utils/utils.ts

index 8b80184..62ab55e 100644 (file)
   This option is enabled only for instantiate jobs.
   IF the user click on this option, the previous instantiation is opened in drawing board, 
   and the user can create another one from this template.
+  
+* FLAG_2002_UNLIMITED_MAX 
+  when flag is true and max_instances is not declare than user can add unlimited VND, NETWORK, VFMODULE,
+  User can duplicate up to 10 record in single time.
+  If the flag is false and max_instances is not declare the max will be 1 else max_instances value.
index 26bfec5..990ec60 100644 (file)
@@ -82,6 +82,7 @@ public enum Features implements Feature {
     FLAG_2004_INSTANTIATION_STATUS_FILTER,
     FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE,
     FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER,
+    FLAG_2002_UNLIMITED_MAX,
     ;
 
 
index 0049a42..b678702 100644 (file)
@@ -584,6 +584,7 @@ describe('Drawing board', function () {
           "FLAG_SERVICE_MODEL_CACHE": true,
           "FLAG_1906_COMPONENT_INFO" : false,
           "FLAG_2002_VNF_PLATFORM_MULTI_SELECT" : false,
+          "FLAG_2002_UNLIMITED_MAX" : true
         },
         "type": "[FLAGS] Update"
       },
index 688d42e..d77460a 100644 (file)
@@ -331,7 +331,7 @@ describe('View only drawing board', function () {
       ['Model version', '2.0'],
       ['Model customization ID', '91415b44-753d-494c-926a-456a9172bbb9'],
       ['Min instances', '0'],
-      ['Max instances', '1']
+      //['Max instances', '1']
     ];
     const extraLabelsAndValuesForInstance = [['Instance type', 'VNF2_INSTANCE_TYPE'],['In maintenance','true'], ['Instance ID', 'VNF2_INSTANCE_ID']];
     testComponentInfoByType('node-VF_vGeraldine 0', labelsAndValuesForModel,'VNF INFO',
index 5e92e4f..531bad3 100644 (file)
@@ -22,5 +22,6 @@
   "FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER": true,
   "FLAG_2004_INSTANTIATION_STATUS_FILTER": true,
   "FLAG_2004_INSTANTIATION_TEMPLATES_POPUP" : false,
+  "FLAG_2002_UNLIMITED_MAX" : true,
   "FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE": true
 }
index 3483885..50bfa93 100644 (file)
@@ -3,9 +3,10 @@ import {LogService} from '../../../shared/utils/log/log.service';
 import {NgRedux} from '@angular-redux/store';
 import {ITreeNode} from "angular-tree-component/dist/defs/api";
 import {SdcUiServices} from "onap-ui-angular";
-import {IModalConfig} from "onap-ui-angular/dist/components/common";
+import {IModalConfig} from 'onap-ui-angular/dist/components/common';
 import {AppState} from "../../../shared/store/reducers";
 import {getTestBed, TestBed} from "@angular/core/testing";
+import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
 
 class MockAppStore<T> {
   getState(){
@@ -52,15 +53,23 @@ class MockAppStore<T> {
 
 class MockModalService<T> {}
 
+class MockFeatureFlagsService extends  FeatureFlagsService{
+  getAllFlags(): { [p: string]: boolean } {
+    return {};
+  }
+}
+
 describe('Drawing board tree service', () => {
   let injector;
   let service: DuplicateService;
   let store : NgRedux<AppState>;
+  let featureFlagsService : FeatureFlagsService;
   beforeAll(done => (async () => {
     TestBed.configureTestingModule({
       providers : [
         DuplicateService,
         LogService,
+        {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         {provide: NgRedux, useClass: MockAppStore},
         {provide: SdcUiServices.ModalService, useClass: MockModalService}
       ]
@@ -70,6 +79,7 @@ describe('Drawing board tree service', () => {
     injector = getTestBed();
     service = injector.get(DuplicateService);
     store = injector.get(NgRedux);
+    featureFlagsService = injector.get(FeatureFlagsService);
 
   })().then(done).catch(done.fail));
 
@@ -417,6 +427,11 @@ describe('Drawing board tree service', () => {
                 }
               }
 
+            }
+          },
+          global : {
+            flags : {
+
             }
           }
         }
index 5fb5f0b..847790d 100644 (file)
@@ -11,15 +11,18 @@ import {TypeNodeInformation} from "../typeNodeInformation.model";
 import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
 import {changeInstanceCounter, duplicateBulkInstances} from "../../../shared/storeUtil/utils/general/general.actions";
 import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
+import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
+import {Utils} from "../../../shared/utils/utils";
 
 @Injectable()
 export class DuplicateService {
 
-  constructor(private _logService : LogService,  private _store: NgRedux<AppState>, modalService: SdcUiServices.ModalService) {
+  constructor(private _logService: LogService, private _store: NgRedux<AppState>, modalService: SdcUiServices.ModalService) {
     this.modalService = modalService;
   }
 
-  numberOfDuplicates:number;
+  numberOfDuplicates: number;
+
   setNumberOfDuplicates(numberOfDuplicates: number) {
     this.numberOfDuplicates = numberOfDuplicates;
   }
@@ -30,10 +33,9 @@ export class DuplicateService {
   storeKey: string = null;
   padding = '0000';
   modalService: SdcUiServices.ModalService;
-  store : NgRedux<AppState>;
-  existingNames : {[key: string] : any};
-  currentNode : ITreeNode = null;
-
+  store: NgRedux<AppState>;
+  existingNames: { [key: string]: any };
+  currentNode: ITreeNode = null;
 
 
   canDuplicate(node: ITreeNode): boolean {
@@ -41,25 +43,31 @@ export class DuplicateService {
     return node.data.type === 'VF' || node.data.type === 'VL';
   }
 
-  isEnabled(node: ITreeNode, store: NgRedux<AppState>, serviceId : string): boolean {
-    if(!_.isNil(node) && !_.isNil(node.data.menuActions['duplicate'])){
-      if(this.hasMissingData(node)) return false;
-      const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node);
-      const max : number = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][node.data.modelName].properties['max_instances'] || 1;
+  isEnabled(node: ITreeNode, store: NgRedux<AppState>, serviceId: string): boolean {
+    if (!_.isNil(node) && !_.isNil(node.data.menuActions['duplicate'])) {
+      if (this.hasMissingData(node)) return false;
+      const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
+      const flags = FeatureFlagsService.getAllFlags(store);
+
       const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][node.data.modelUniqueId];
+      const maxInstances = Utils.getMaxFirstLevel(store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][node.data.modelName].properties, flags);
+      if (_.isNil(maxInstances)) {
+        return true;
+      } else {
+        return maxInstances - currentExisting > 0;
+      }
 
-      return max - currentExisting > 0;
-    }else {
+    } else {
       return false;
     }
   }
 
-  hasMissingData(node : ITreeNode): boolean {
-    if(!_.isNil(node)){
-      if(node.data.missingData) return true;
-      if(!_.isNil(node.data.children)){
-        for(let child of node.data.children) {
-          if(child.missingData){
+  hasMissingData(node: ITreeNode): boolean {
+    if (!_.isNil(node)) {
+      if (node.data.missingData) return true;
+      if (!_.isNil(node.data.children)) {
+        for (let child of node.data.children) {
+          if (child.missingData) {
             return true;
           }
         }
@@ -69,16 +77,22 @@ export class DuplicateService {
     return false;
   }
 
-  getRemainsInstance(modelId : string, modelName : string, serviceId : string, store: NgRedux<AppState>, node : ITreeNode) : number {
-    const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node);
-    const properties  = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][modelName].properties;
-    const currentExisting : number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][modelId];
-    return (!_.isNil(properties) && !_.isNil(properties['max_instances'])) ? properties['max_instances'] - currentExisting : null;
+  getRemainsInstance(modelId: string, modelName: string, serviceId: string, store: NgRedux<AppState>, node: ITreeNode): number {
+    const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
+    const properties = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][modelName].properties;
+    const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][modelId];
+
+    const flags = FeatureFlagsService.getAllFlags(store);
+    const maxInstances = Utils.getMaxFirstLevel(properties, flags);
+    if (_.isNil(maxInstances)) {
+      return 10;
+    } else {
+      return maxInstances - currentExisting;
+    }
   }
 
 
-
-  openDuplicateModal(currentServiceId: string, currentUuid: string, currentId: string, storeKey : string, numberOfDuplicate: number, _store : NgRedux<AppState>, node: ITreeNode): IModalConfig {
+  openDuplicateModal(currentServiceId: string, currentUuid: string, currentId: string, storeKey: string, numberOfDuplicate: number, _store: NgRedux<AppState>, node: ITreeNode): IModalConfig {
     this.currentInstanceId = currentId;
     this.currentServiceId = currentServiceId;
     this.maxNumberOfDuplicate = this.getRemainsInstance(currentUuid, currentId, currentServiceId, _store, node);
@@ -87,7 +101,7 @@ export class DuplicateService {
     this.currentNode = node;
 
 
-    return  {
+    return {
       size: SdcUiCommon.ModalSize.medium,
       title: 'Duplicate Node',
       type: SdcUiCommon.ModalType.custom,
@@ -98,12 +112,12 @@ export class DuplicateService {
     };
   }
 
-  duplicate(node : ITreeNode): void {
-    const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node);
+  duplicate(node: ITreeNode): void {
+    const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
     this.existingNames = this.store.getState().service.serviceInstance[this.currentServiceId].existingNames;
-    const toClone  = this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName][this.storeKey];
+    const toClone = this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName][this.storeKey];
     let newObjects = {};
-    for(let i = 0; i < this.numberOfDuplicates; i++) {
+    for (let i = 0; i < this.numberOfDuplicates; i++) {
       const uniqueStoreKey = this.generateUniqueStoreKey(this.currentServiceId, this.currentInstanceId, this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName], newObjects);
       const clone = this.cloneVnf(toClone, this.currentInstanceId);
       newObjects[uniqueStoreKey] = clone;
@@ -114,12 +128,12 @@ export class DuplicateService {
   }
 
 
-  cloneVnf(vnf : VnfInstance, originalName: string): VnfInstance {
-    let newUniqueVnf : VnfInstance = _.cloneDeep(vnf);
+  cloneVnf(vnf: VnfInstance, originalName: string): VnfInstance {
+    let newUniqueVnf: VnfInstance = _.cloneDeep(vnf);
 
     newUniqueVnf.originalName = originalName;
     newUniqueVnf.trackById = DefaultDataGeneratorService.createRandomTrackById();
-    if (!_.isNil(vnf.instanceName)){
+    if (!_.isNil(vnf.instanceName)) {
       newUniqueVnf.instanceName = this.ensureUniqueNameOrGenerateOne(vnf.instanceName);
     }
 
@@ -127,10 +141,10 @@ export class DuplicateService {
       const vfModuleModel: VfModuleMap = vnf.vfModules[vf_module_model_name];
       for (let vfModule in vfModuleModel) {
         newUniqueVnf.vfModules[vf_module_model_name][vfModule].trackById = DefaultDataGeneratorService.createRandomTrackById();
-        if (!_.isNil(vfModuleModel[vfModule].instanceName)){
+        if (!_.isNil(vfModuleModel[vfModule].instanceName)) {
           newUniqueVnf.vfModules[vf_module_model_name][vfModule].instanceName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].instanceName);
         }
-        if (!_.isNil(vfModuleModel[vfModule].volumeGroupName)){
+        if (!_.isNil(vfModuleModel[vfModule].volumeGroupName)) {
           newUniqueVnf.vfModules[vf_module_model_name][vfModule].volumeGroupName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].volumeGroupName);
         }
       }
@@ -138,7 +152,7 @@ export class DuplicateService {
     return newUniqueVnf;
   }
 
-  ensureUniqueNameOrGenerateOne(instanceName){
+  ensureUniqueNameOrGenerateOne(instanceName) {
     let uniqueInstanceName = instanceName;
     if (this.isAlreadyExists(instanceName, this.existingNames)) {
       uniqueInstanceName = this.generateNextUniqueName(instanceName, this.existingNames);
@@ -148,33 +162,33 @@ export class DuplicateService {
   }
 
 
-  isAlreadyExists(name : string, existingNames : {[key: string] : any}){
+  isAlreadyExists(name: string, existingNames: { [key: string]: any }) {
     return _.has(existingNames, name.toLowerCase());
   }
 
-  generateNextUniqueName(name : string, existingNames : {[key: string] : any})  :string{
+  generateNextUniqueName(name: string, existingNames: { [key: string]: any }): string {
     let suffix = "000";
     let counter = 1;
-    if (name.match(/^.*_[\d]{3}$/)){
+    if (name.match(/^.*_[\d]{3}$/)) {
       name = name.substring(0, name.length - 4);
     }
 
-    while(true){
-      let paddingNumber : string = this.getNumberAsPaddingString(counter, suffix);
+    while (true) {
+      let paddingNumber: string = this.getNumberAsPaddingString(counter, suffix);
       let candidateUniqueName = name + '_' + paddingNumber;
-      if(!this.isAlreadyExists(candidateUniqueName, existingNames)){
+      if (!this.isAlreadyExists(candidateUniqueName, existingNames)) {
         return candidateUniqueName;
       }
       counter++;
     }
   }
 
-  generateUniqueStoreKey(serviceId : string, objectName : string, existing : any, newObjects: any) : string {
+  generateUniqueStoreKey(serviceId: string, objectName: string, existing: any, newObjects: any): string {
     let counter = 1;
-    while(true){
-      let paddingNumber : string = this.getNumberAsPaddingString(counter, this.padding);
+    while (true) {
+      let paddingNumber: string = this.getNumberAsPaddingString(counter, this.padding);
       const name = objectName + ':' + paddingNumber;
-      if(_.isNil(existing[name]) && _.isNil(newObjects[name])){
+      if (_.isNil(existing[name]) && _.isNil(newObjects[name])) {
         return name;
       }
       counter++;
index 10c1366..089f812 100644 (file)
@@ -12,6 +12,7 @@ import {DrawingBoardModes} from "../../../drawing-board.modes";
 import {IframeService} from "../../../../../shared/utils/iframe.service";
 import {DuplicateService} from "../../../duplicate/duplicate.service";
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
+import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 
 class MockAppStore<T> {
   getState() {
@@ -19,27 +20,27 @@ class MockAppStore<T> {
       global: {
         'drawingBoardStatus': DrawingBoardModes.CREATE
       },
-      service : {
-        serviceHierarchy : {
-          'servicedId' : {
-            'networks' : {
-              'networkName' : {
-                'properties' : {
-                  'max_instances' : 1
+      service: {
+        serviceHierarchy: {
+          'servicedId': {
+            'networks': {
+              'networkName': {
+                'properties': {
+                  'max_instances': 1
                 }
               }
             }
           }
         },
-        serviceInstance : {
-          'servicedId' : {
-            'existingNetworksCounterMap' : {
-              'networkId' : 1
+        serviceInstance: {
+          'servicedId': {
+            'existingNetworksCounterMap': {
+              'networkId': 1
             },
-            'networks' : {
-              'networkName' :{
+            'networks': {
+              'networkName'{
                 'action': 'Create',
-                'originalName' : 'networkName'
+                'originalName': 'networkName'
               }
             }
           }
@@ -48,15 +49,24 @@ class MockAppStore<T> {
     }
   }
 }
+
+class MockFeatureFlagsService extends FeatureFlagsService {
+  getAllFlags(): { [p: string]: boolean } {
+    return {};
+  }
+}
+
+
 describe('Network Model Info', () => {
   let injector;
-  let  _dynamicInputsService : DynamicInputsService;
-  let  _sharedTreeService : SharedTreeService;
+  let _dynamicInputsService: DynamicInputsService;
+  let _sharedTreeService: SharedTreeService;
   let networkModel: NetworkModelInfo;
-  let _dialogService : DialogService;
-  let _networkPopupService :  NetworkPopupService;
-  let _duplicateService : DuplicateService;
-  let _iframeService : IframeService;
+  let _dialogService: DialogService;
+  let _networkPopupService: NetworkPopupService;
+  let _duplicateService: DuplicateService;
+  let _iframeService: IframeService;
+  let _featureFlagsService: FeatureFlagsService;
 
   beforeAll(done => (async () => {
     TestBed.configureTestingModule({
@@ -69,13 +79,16 @@ describe('Network Model Info', () => {
         IframeService,
         DuplicateService,
         {provide: NgRedux, useClass: MockAppStore},
+        {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         MockNgRedux]
     });
     await TestBed.compileComponents();
 
     injector = getTestBed();
     _sharedTreeService = injector.get(SharedTreeService);
-    networkModel = new NetworkModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _networkPopupService, _duplicateService, null, _iframeService, MockNgRedux.getInstance());
+    _featureFlagsService = injector.get(FeatureFlagsService);
+
+    networkModel = new NetworkModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _networkPopupService, _duplicateService, null, _iframeService, _featureFlagsService, MockNgRedux.getInstance());
   })().then(done).catch(done.fail));
 
   test('NetworkModelInfo should be defined', () => {
@@ -137,39 +150,37 @@ describe('Network Model Info', () => {
     expect(model.type).toEqual('VL');
   });
 
-  test('showNodeIcons should return false if reachLimit of max', ()=>{
-    let serviceId : string = 'servicedId';
+  test('showNodeIcons should return false if reachLimit of max', () => {
+    let serviceId: string = 'servicedId';
     let node = {
-      data : {
-        id : 'networkId',
-        name : 'networkName',
-        modelCustomizationId : 'modelCustomizationId'
+      data: {
+        id: 'networkId',
+        name: 'networkName',
+        modelCustomizationId: 'modelCustomizationId'
       }
     };
     jest.spyOn(_sharedTreeService, 'getExistingInstancesWithDeleteMode').mockReturnValue(0);
     jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({
-      global : {},
-      service : {
-        serviceHierarchy : {
-          'servicedId' : {
-            'networks' : {
-              'networkName' : {
-                'properties' : {
-                  'max_instances' : 1
+      global: {},
+      service: {
+        serviceHierarchy: {
+          'servicedId': {
+            'networks': {
+              'networkName': {
+                'properties': {
+                  'max_instances': 1
                 }
               }
             }
           }
         },
-        serviceInstance : {
-          'servicedId' : {
-            'existingNetworksCounterMap' : {
-              'modelCustomizationId' : 1
+        serviceInstance: {
+          'servicedId': {
+            'existingNetworksCounterMap': {
+              'modelCustomizationId': 1
             },
-            'networks' : {
-              'networkName' :{
-
-              }
+            'networks': {
+              'networkName': {}
             }
           }
         }
@@ -177,41 +188,39 @@ describe('Network Model Info', () => {
     });
 
     let result = networkModel.showNodeIcons(<any>node, serviceId);
-    expect(result).toEqual(new AvailableNodeIcons(true , false));
+    expect(result).toEqual(new AvailableNodeIcons(true, false));
   });
 
-  test('showNodeIcons should return true if not reachLimit of max', ()=>{
-    let serviceId : string = 'servicedId';
+  test('showNodeIcons should return true if not reachLimit of max', () => {
+    let serviceId: string = 'servicedId';
     let node = {
-      data : {
-        id : 'networkId',
-        name : 'networkName'
+      data: {
+        id: 'networkId',
+        name: 'networkName'
       }
     };
     jest.spyOn(_sharedTreeService, 'getExistingInstancesWithDeleteMode').mockReturnValue(0);
     jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({
-      global : {},
-      service : {
-        serviceHierarchy : {
-          'servicedId' : {
-            'networks' : {
-              'networkName' : {
-                'properties' : {
-                  'max_instances' : 2
+      global: {},
+      service: {
+        serviceHierarchy: {
+          'servicedId': {
+            'networks': {
+              'networkName': {
+                'properties': {
+                  'max_instances': 2
                 }
               }
             }
           }
         },
-        serviceInstance : {
-          'servicedId' : {
-            'existingNetworksCounterMap' : {
-              'networkId' : 1
+        serviceInstance: {
+          'servicedId': {
+            'existingNetworksCounterMap': {
+              'networkId': 1
             },
-            'networks' : {
-              'networkName' :{
-
-              }
+            'networks': {
+              'networkName': {}
             }
           }
         }
@@ -219,34 +228,34 @@ describe('Network Model Info', () => {
     });
 
     let result = networkModel.showNodeIcons(<any>node, serviceId);
-    expect(result).toEqual(new AvailableNodeIcons(true , false));
+    expect(result).toEqual(new AvailableNodeIcons(true, false));
   });
 
-  test('getNodeCount should return number of nodes', ()=>{
-    let serviceId : string = 'servicedId';
+  test('getNodeCount should return number of nodes', () => {
+    let serviceId: string = 'servicedId';
     jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({
-      global : {},
-      service : {
-        serviceHierarchy : {
-          'servicedId' : {
-            'networks' : {
-              'networkName' : {
-                'properties' : {
-                  'max_instances' : 1
+      global: {},
+      service: {
+        serviceHierarchy: {
+          'servicedId': {
+            'networks': {
+              'networkName': {
+                'properties': {
+                  'max_instances': 1
                 }
               }
             }
           }
         },
-        serviceInstance : {
-          'servicedId' : {
-            'existingNetworksCounterMap' : {
-              'modelCustomizationId' : 1
+        serviceInstance: {
+          'servicedId': {
+            'existingNetworksCounterMap': {
+              'modelCustomizationId': 1
             },
-            'networks' : {
-              'networkName' :{
+            'networks': {
+              'networkName'{
                 'action': 'Create',
-                'originalName' : 'networkName'
+                'originalName': 'networkName'
               }
             }
           }
@@ -255,24 +264,24 @@ describe('Network Model Info', () => {
     });
 
     let node = {
-      data : {
-        id : 'networkId',
-        name : 'networkName',
+      data: {
+        id: 'networkId',
+        name: 'networkName',
         action: 'Create',
-        modelCustomizationId : "modelCustomizationId",
+        modelCustomizationId: "modelCustomizationId",
         modelUniqueId: "modelCustomizationId"
       }
     };
-    let result = networkModel.getNodeCount(<any>node , serviceId);
+    let result = networkModel.getNodeCount(<any>node, serviceId);
     expect(result).toEqual(1);
 
     node.data.modelCustomizationId = 'networkId_notExist';
     node.data.modelUniqueId = 'networkId_notExist';
-    result = networkModel.getNodeCount(<any>node , serviceId);
+    result = networkModel.getNodeCount(<any>node, serviceId);
     expect(result).toEqual(0);
   });
 
-  test('getMenuAction: showAuditInfoNetwork', ()=>{
+  test('getMenuAction: showAuditInfoNetwork', () => {
 
     jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({
       global: {
@@ -281,7 +290,7 @@ describe('Network Model Info', () => {
     });
     jest.spyOn(_sharedTreeService, 'isRetryMode').mockReturnValue(true);
     let node = {
-      data : {
+      data: {
         "modelId": "6b528779-44a3-4472-bdff-9cd15ec93450",
         "action": "Create",
         "isFailed": true,
@@ -300,7 +309,7 @@ describe('Network Model Info', () => {
   test('Info for network should be correct', () => {
     const model = getNetworkModel();
     const instance = getNetworkInstance();
-    let actualNetworkInfo = networkModel.getInfo(model,instance);
+    let actualNetworkInfo = networkModel.getInfo(model, instance);
     let expectedNetworkInfo = [
       ModelInformationItem.createInstance('Network role', "network role 1, network role 2"),
       ModelInformationItem.createInstance("Route target id", null),
@@ -309,26 +318,27 @@ describe('Network Model Info', () => {
     expect(actualNetworkInfo).toEqual(expectedNetworkInfo);
   });
 
-  function getNetworkModel(){
+  function getNetworkModel() {
     return {
-      "customizationUuid":"94fdd893-4a36-4d70-b16a-ec29c54c184f",
-      "name":"ExtVL",
-      "version":"37.0",
-      "description":"ECOMP generic virtual link (network) base type for all other service-level and global networks",
-      "uuid":"ddc3f20c-08b5-40fd-af72-c6d14636b986",
-      "invariantUuid":"379f816b-a7aa-422f-be30-17114ff50b7c",
-      "max":1,
-      "min":0,
-      "isEcompGeneratedNaming":false,
-      "type":"VL",
-      "modelCustomizationName":"ExtVL 0",
-      "roles":["network role 1"," network role 2"],
-      "properties":{
-        "network_role":"network role 1, network role 2",
+      "customizationUuid": "94fdd893-4a36-4d70-b16a-ec29c54c184f",
+      "name": "ExtVL",
+      "version": "37.0",
+      "description": "ECOMP generic virtual link (network) base type for all other service-level and global networks",
+      "uuid": "ddc3f20c-08b5-40fd-af72-c6d14636b986",
+      "invariantUuid": "379f816b-a7aa-422f-be30-17114ff50b7c",
+      "max": 1,
+      "min": 0,
+      "isEcompGeneratedNaming": false,
+      "type": "VL",
+      "modelCustomizationName": "ExtVL 0",
+      "roles": ["network role 1", " network role 2"],
+      "properties": {
+        "network_role": "network role 1, network role 2",
         "network_assignments":
           "{is_external_network=false, ipv4_subnet_default_assignment={min_subnets_count=1}, ecomp_generated_network_assignment=false, ipv6_subnet_default_assignment={min_subnets_count=1}}",
-        "exVL_naming":"{ecomp_generated_naming=true}","network_flows":"{is_network_policy=false, is_bound_to_vpn=false}",
-        "network_homing":"{ecomp_selected_instance_node_target=false}"
+        "exVL_naming": "{ecomp_generated_naming=true}",
+        "network_flows": "{is_network_policy=false, is_bound_to_vpn=false}",
+        "network_homing": "{ecomp_selected_instance_node_target=false}"
       }
     };
 
@@ -370,9 +380,7 @@ describe('Network Model Info', () => {
   }
 
 
-
-
-  function getServiceHierarchy(){
+  function getServiceHierarchy() {
     return {
       "service": {
         "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450",
index 3ed40cd..3ba4a2c 100644 (file)
@@ -30,6 +30,7 @@ import {
 import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
 import {ComponentInfoType} from "../../../component-info/component-info-model";
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
+import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 
 export class NetworkModelInfo implements ILevelNodeInfo {
   constructor(private _dynamicInputsService: DynamicInputsService,
@@ -39,6 +40,7 @@ export class NetworkModelInfo implements ILevelNodeInfo {
               private _duplicateService: DuplicateService,
               private modalService: SdcUiServices.ModalService,
               private _iframeService: IframeService,
+              private _featureFlagsService: FeatureFlagsService,
               private _store: NgRedux<AppState>) {
   }
 
@@ -70,7 +72,7 @@ export class NetworkModelInfo implements ILevelNodeInfo {
    ************************************************************/
   getModel = (networkModelId: string, instance: NetworkInstance, serviceHierarchy): NetworkModel => {
     const originalModelName = instance.originalName ? instance.originalName : networkModelId;
-    return new NetworkModel(serviceHierarchy[this.name][originalModelName]);
+    return new NetworkModel(serviceHierarchy[this.name][originalModelName], this._featureFlagsService.getAllFlags());
   };
 
 
@@ -164,8 +166,8 @@ export class NetworkModelInfo implements ILevelNodeInfo {
     counter -= this._sharedTreeService.getExistingInstancesWithDeleteMode(node, serviceModelId, 'networks');
 
     const properties = this._store.getState().service.serviceHierarchy[serviceModelId].networks[node.data.name].properties;
-    const maxInstances: number = !_.isNil(properties) ? (properties.max_instances || 1) : 1;
-    const isReachedLimit = !(maxInstances > counter);
+    const flags = FeatureFlagsService.getAllFlags(this._store);
+    const isReachedLimit: boolean = this._sharedTreeService.isReachedToMaxInstances(properties, counter, flags);
     const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !isReachedLimit;
 
     return new AvailableNodeIcons(showAddIcon, isReachedLimit)
index eb9902f..225d84b 100644 (file)
@@ -28,6 +28,12 @@ class MockAppStore<T> {
   }
 }
 
+class MockFeatureFlagsService extends  FeatureFlagsService{
+  getAllFlags(): { [p: string]: boolean } {
+    return {};
+  }
+}
+
 describe('VFModule Model Info', () => {
   let injector;
   let  _dynamicInputsService : DynamicInputsService;
@@ -38,6 +44,8 @@ describe('VFModule Model Info', () => {
   let _vfModuleUpgradePopupService : VfModuleUpgradePopupService;
   let _iframeService : IframeService;
   let _componentInfoService : ComponentInfoService;
+  let _featureFlagsService : FeatureFlagsService;
+
 
   beforeAll(done => (async () => {
     TestBed.configureTestingModule({
@@ -54,7 +62,7 @@ describe('VFModule Model Info', () => {
         AaiService,
         HttpClient,
         HttpHandler,
-        FeatureFlagsService,
+        {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         ComponentInfoService
       ]
     });
@@ -63,7 +71,8 @@ describe('VFModule Model Info', () => {
     injector = getTestBed();
     _sharedTreeService = injector.get(SharedTreeService);
     _componentInfoService = injector.get(ComponentInfoService)
-    vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _vfModuleUpgradePopupService, _iframeService, MockNgRedux.getInstance(),_componentInfoService);
+    _featureFlagsService = injector.get(FeatureFlagsService);
+    vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _vfModuleUpgradePopupService, _iframeService,_featureFlagsService,  MockNgRedux.getInstance(),_componentInfoService);
 
   })().then(done).catch(done.fail));
 
index 5e14586..e182b8a 100644 (file)
@@ -40,6 +40,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
               private _vfModulePopupService: VfModulePopuopService,
               private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
               private _iframeService: IframeService,
+              private _featureFlagsService: FeatureFlagsService,
               private _store: NgRedux<AppState>,
               private _componentInfoService: ComponentInfoService) {
   }
@@ -306,7 +307,6 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
       maxNodes = vnfModules[node.data.name].properties.maxCountInstances || 1;
     }
     return !(maxNodes > currentNodeCount);
-
   }
 
   getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } {
index 3af4288..d89280f 100644 (file)
@@ -23,6 +23,11 @@ import {AaiService} from "../../../../../shared/services/aaiService/aai.service"
 import {HttpClient, HttpHandler} from "@angular/common/http";
 import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
+class MockFeatureFlagsService extends  FeatureFlagsService{
+  getAllFlags(): { [p: string]: boolean } {
+    return {};
+  }
+}
 
 describe('Vnf Model Info', () => {
  let injector;
@@ -38,6 +43,7 @@ describe('Vnf Model Info', () => {
  let _duplicateService : DuplicateService;
  let _iframeService : IframeService;
  let _componentInfoService : ComponentInfoService;
+ let _featureFlagsService : FeatureFlagsService;
 
   let _store : NgRedux<AppState>;
   let vnfModel: VnfModelInfo;
@@ -57,7 +63,7 @@ describe('Vnf Model Info', () => {
         AaiService,
         HttpClient,
         HttpHandler,
-        FeatureFlagsService,
+        {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         ComponentInfoService,
         IframeService]
     }).compileComponents();
@@ -65,7 +71,7 @@ describe('Vnf Model Info', () => {
     injector = getTestBed();
     _sharedTreeService = injector.get(SharedTreeService);
     _store = injector.get(NgRedux);
-    _componentInfoService = injector.get(ComponentInfoService);
+    _featureFlagsService = injector.get(FeatureFlagsService);
 
     vnfModel = new VnfModelInfo(
       _dynamicInputsService,
@@ -79,6 +85,7 @@ describe('Vnf Model Info', () => {
       null,
       _iframeService,
       _componentInfoService,
+      _featureFlagsService,
       _store);
 
 
index 05d4af1..c1255f5 100644 (file)
@@ -39,6 +39,7 @@ import {ComponentInfoType} from "../../../component-info/component-info-model";
 import {ComponentInfoService} from "../../../component-info/component-info.service";
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
 import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
+import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 
 export class VnfModelInfo implements ILevelNodeInfo {
   constructor(private _dynamicInputsService: DynamicInputsService,
@@ -47,11 +48,12 @@ export class VnfModelInfo implements ILevelNodeInfo {
               private _dialogService: DialogService,
               private _vnfPopupService: VnfPopupService,
               private _vfModulePopupService: VfModulePopuopService,
-              private _vfModuleUpgradePopupService : VfModuleUpgradePopupService,
+              private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
               private _duplicateService: DuplicateService,
               private modalService: SdcUiServices.ModalService,
               private _iframeService: IframeService,
               private _componentInfoService: ComponentInfoService,
+              private _featureFlagsService: FeatureFlagsService,
               private _store: NgRedux<AppState>) {
   }
 
@@ -87,7 +89,7 @@ export class VnfModelInfo implements ILevelNodeInfo {
    ************************************************************/
   getModel = (vnfModelId: string, instance: VnfInstance, serviceHierarchy): VNFModel => {
     const originalModelName = instance.originalName ? instance.originalName : vnfModelId;
-    return new VNFModel(serviceHierarchy[this.name][originalModelName]);
+    return new VNFModel(serviceHierarchy[this.name][originalModelName], this._featureFlagsService.getAllFlags());
   };
 
 
@@ -104,7 +106,7 @@ export class VnfModelInfo implements ILevelNodeInfo {
     node.typeName = this.typeName;
     node.menuActions = this.getMenuAction(<any>node, model.uuid);
     node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
-    node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage: "";
+    node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
     node = this._sharedTreeService.addingStatusProperty(node);
     return node;
   };
@@ -113,7 +115,7 @@ export class VnfModelInfo implements ILevelNodeInfo {
    * return next level object (VFModule)
    ************************************************************/
   getNextLevelObject = (): VFModuleModelInfo => {
-    return new VFModuleModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._vfModulePopupService, this._vfModuleUpgradePopupService, this._iframeService, this._store, this._componentInfoService);
+    return new VFModuleModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._vfModulePopupService, this._vfModuleUpgradePopupService, this._iframeService, this._featureFlagsService, this._store, this._componentInfoService);
   };
 
   /***********************************************************
@@ -181,8 +183,8 @@ export class VnfModelInfo implements ILevelNodeInfo {
     counter -= this._sharedTreeService.getExistingInstancesWithDeleteMode(node, serviceModelId, 'vnfs');
 
     const properties = this._store.getState().service.serviceHierarchy[serviceModelId].vnfs[node.data.name].properties;
-    const maxInstances: number = !_.isNil(properties) ? (properties.max_instances || 1) : 1;
-    const isReachedLimit = !(maxInstances > counter);
+    const flags = FeatureFlagsService.getAllFlags(this._store);
+    const isReachedLimit: boolean = this._sharedTreeService.isReachedToMaxInstances(properties, counter, flags);
     const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !isReachedLimit;
     return new AvailableNodeIcons(showAddIcon, isReachedLimit)
   }
@@ -211,9 +213,9 @@ export class VnfModelInfo implements ILevelNodeInfo {
       },
       showAuditInfo: {
         method: (node, serviceModelId) => {
-            const instance = this._store.getState().service.serviceInstance[serviceModelId].vnfs[node.data.vnfStoreKey];
-            this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VNF', this);
-          },
+          const instance = this._store.getState().service.serviceInstance[serviceModelId].vnfs[node.data.vnfStoreKey];
+          this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VNF', this);
+        },
         visible: (node) => this._sharedTreeService.shouldShowAuditInfo(node),
         enable: (node) => this._sharedTreeService.shouldShowAuditInfo(node)
       },
@@ -324,8 +326,8 @@ export class VnfModelInfo implements ILevelNodeInfo {
 
   getInfo(model, instance): ModelInformationItem[] {
     const modelInformation = !_.isEmpty(model) ? [
-      ModelInformationItem.createInstance("Min instances",  !_.isNull(model.min)? String(model.min): null),
-      ModelInformationItem.createInstance("Max instances",  !_.isNull(model.max)? String(model.max): null)
+      ModelInformationItem.createInstance("Min instances", !_.isNull(model.min) ? String(model.min) : null),
+      ModelInformationItem.createInstance("Max instances", !_.isNull(model.max) ? String(model.max) : null)
     ] : [];
 
     const instanceInfo = !_.isEmpty(instance) ? [
index 4c779a3..3dbc60a 100644 (file)
@@ -26,12 +26,14 @@ import {
   undoDeleteActionVrfInstance
 } from "../../../../../shared/storeUtil/utils/vrf/vrf.actions";
 import * as _ from "lodash";
+import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 
 export class VrfModelInfo implements ILevelNodeInfo {
   constructor(private _store: NgRedux<AppState>,
               private _sharedTreeService: SharedTreeService,
               private _dialogService: DialogService,
               private _iframeService: IframeService,
+              private _featureFlagsService : FeatureFlagsService,
               private _networkStepService: NetworkStepService,
               private _vpnStepService: VpnStepService) {
   }
@@ -70,7 +72,7 @@ export class VrfModelInfo implements ILevelNodeInfo {
       return new VpnModelInfo(this._store, this._sharedTreeService);
     } else {
       if (nextLevelType === 'networks') {
-        return new NetworkModelInfo(null, this._sharedTreeService, null, null, null, null, null, this._store);
+        return new NetworkModelInfo(null, this._sharedTreeService, null, null, null, null, null,this._featureFlagsService,  this._store);
       }
     }
   };
index c101f44..75ae1e1 100644 (file)
@@ -3,11 +3,13 @@ import {ILevelNodeInfo} from "../models/basic.model.info";
 import {ObjectToTreeService} from "../objectToTree.service";
 import * as _ from "lodash";
 import {IModelTreeNodeModel} from "../../../objectsToTree/objectToModelTree/modelTreeNode.model";
+import {FeatureFlagsService} from "../../../../shared/services/featureFlag/feature-flags.service";
 
 @Injectable()
 export class ObjectToModelTreeService {
   numberOfPlusButton: number;
-  constructor(private _objectToTreeService: ObjectToTreeService) {
+
+  constructor(private _objectToTreeService: ObjectToTreeService, private _featureFlagsService: FeatureFlagsService) {
   }
 
   /***********************************************************
@@ -18,9 +20,10 @@ export class ObjectToModelTreeService {
     let _this = this;
     const firstLevelOptions: ILevelNodeInfo[] = _this._objectToTreeService.getFirstLevelOptions();
     let nodes = [];
+    let flags = this._featureFlagsService.getAllFlags();
     for (let option of firstLevelOptions) {
       _.forOwn(serviceModel[option.name], function (item, key) {
-        nodes.push(_this.addFirstLevelModel(serviceModel.service.uuid, key, item, item.type, serviceModel, option));
+        nodes.push(_this.addFirstLevelModel(serviceModel.service.uuid, key, item, item.type, serviceModel, option, flags));
       });
     }
 
@@ -30,10 +33,10 @@ export class ObjectToModelTreeService {
     return nodes;
   }
 
-  calculateNumberOfNodesWithPlusIcon(serviceModel, nodes) : void {
-    this.numberOfPlusButton = nodes.reduce((sum, node)=>{
-      let showNodeIconResult = node.showNodeIcons({data : node}, serviceModel.service.uuid);
-      return (!_.isNil(showNodeIconResult) && showNodeIconResult.addIcon && !showNodeIconResult.vIcon) ?  sum + 1 : sum;
+  calculateNumberOfNodesWithPlusIcon(serviceModel, nodes): void {
+    this.numberOfPlusButton = nodes.reduce((sum, node) => {
+      let showNodeIconResult = node.showNodeIcons({data: node}, serviceModel.service.uuid);
+      return (!_.isNil(showNodeIconResult) && showNodeIconResult.addIcon && !showNodeIconResult.vIcon) ? sum + 1 : sum;
     }, 0);
   }
 
@@ -47,9 +50,9 @@ export class ObjectToModelTreeService {
    * @param parentModel - current parent Model object
    * @param levelNodeInfo - current level node information
    ************************************************************/
-  private addFirstLevelModel(serviceId: string, name, currentModel, type, parentModel, levelNodeInfo: ILevelNodeInfo) {
-    let node = ObjectToModelTreeService.convertItemToTreeNode(serviceId, name, currentModel, type, null, levelNodeInfo);
-    node.children = this.addNextLevelNodes(serviceId, currentModel, parentModel, levelNodeInfo, node);
+  private addFirstLevelModel(serviceId: string, name, currentModel, type, parentModel, levelNodeInfo: ILevelNodeInfo, flags?: { [key: string]: boolean }) {
+    let node = ObjectToModelTreeService.convertItemToTreeNode(serviceId, name, currentModel, type, null, levelNodeInfo, flags);
+    node.children = this.addNextLevelNodes(serviceId, currentModel, parentModel, levelNodeInfo, node, flags);
     return node;
   }
 
@@ -61,13 +64,13 @@ export class ObjectToModelTreeService {
    * @param levelNodeInfo - current level node information
    * @param parentNode - parent node.
    ************************************************************/
-  addNextLevelNodes(serviceId: string, currentModel, parentModel, levelNodeInfo: ILevelNodeInfo, parentNode): any[] {
+  addNextLevelNodes(serviceId: string, currentModel, parentModel, levelNodeInfo: ILevelNodeInfo, parentNode, flags?: { [key: string]: boolean }): any[] {
     if (!_.isNil(levelNodeInfo.childNames) && levelNodeInfo.childNames.length > 0) {
       levelNodeInfo.childNames.forEach(function (childName) {
         if (!_.isNil(currentModel[childName])) {
           let nextLevelNodeInfo = levelNodeInfo.getNextLevelObject.apply(this, [childName]);
           parentNode.children = Object.keys(currentModel[childName]).map((key) =>
-            ObjectToModelTreeService.convertItemToTreeNode(serviceId, key, currentModel[childName][key], childName, currentModel, nextLevelNodeInfo));
+            ObjectToModelTreeService.convertItemToTreeNode(serviceId, key, currentModel[childName][key], childName, currentModel, nextLevelNodeInfo, flags));
         }
       })
     }
@@ -84,17 +87,18 @@ export class ObjectToModelTreeService {
    * @param parentModel - current parent model
    * @param levelNodeInfo - current levelNodeInfo object
    ************************************************************/
-  static convertItemToTreeNode(serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo) {
-    let node : IModelTreeNodeModel = {
+  static convertItemToTreeNode(serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo, flags?: { [key: string]: boolean }) {
+    const type: string = levelNodeInfo.getType();
+    let node: IModelTreeNodeModel = {
       id: currentModel.customizationUuid || currentModel.uuid,
-      modelCustomizationId : currentModel.customizationUuid,
-      modelVersionId:  currentModel.uuid,
-      modelUniqueId : currentModel.customizationUuid || currentModel.uuid,
+      modelCustomizationId: currentModel.customizationUuid,
+      modelVersionId: currentModel.uuid,
+      modelUniqueId: currentModel.customizationUuid || currentModel.uuid,
       name: name,
       tooltip: levelNodeInfo.getTooltip(),
-      type: levelNodeInfo.getType(),
+      type,
       count: currentModel.count || 0,
-      max: currentModel.max || 1,
+      max: ObjectToModelTreeService.getMax(currentModel, type, flags),
       children: [],
       disabled: false,
       dynamicInputs: levelNodeInfo.updateDynamicInputsDataFromModel(currentModel),
@@ -105,15 +109,24 @@ export class ObjectToModelTreeService {
     return node;
   }
 
+  static getMax(currentModel, type, flags: { [key: string]: boolean }) {
+    if (flags && !!flags['FLAG_2002_UNLIMITED_MAX'] && (type === 'VF' || type === 'Network' || type === 'VFmodule')) {
+      return !_.isNil(currentModel.max) ? currentModel.max : null;
+    } else {
+      return currentModel.max || 1
+    }
+  }
 
-  static addExtraFunctionality(node, serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo){
+
+  static addExtraFunctionality(node, serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo) {
     node.onAddClick = (node, serviceId) => levelNodeInfo.onClickAdd(node, serviceId);
     node.getNodeCount = (node, serviceId) => levelNodeInfo.getNodeCount(node, serviceId);
     node.getMenuAction = (node, serviceId) => levelNodeInfo.getMenuAction(node, serviceId);
     node.showNodeIcons = (node, serviceId) => levelNodeInfo.showNodeIcons(node, serviceId);
     node.typeName = levelNodeInfo.typeName;
     node.getModel = levelNodeInfo.getModel.bind(levelNodeInfo);
-    node.getInfo = !_.isNil(levelNodeInfo.getInfo) ? levelNodeInfo.getInfo.bind(levelNodeInfo) : ()=>{};
+    node.getInfo = !_.isNil(levelNodeInfo.getInfo) ? levelNodeInfo.getInfo.bind(levelNodeInfo) : () => {
+    };
     node.componentInfoType = levelNodeInfo.componentInfoType;
     return node;
   }
index 443741f..1e68251 100644 (file)
@@ -25,6 +25,7 @@ import {VrfModelInfo} from "./models/vrf/vrf.model.info";
 import {NetworkStepService} from "./models/vrf/vrfModal/networkStep/network.step.service";
 import {VpnStepService} from "./models/vrf/vrfModal/vpnStep/vpn.step.service";
 import { VfModuleUpgradePopupService } from "../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
+import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
 
 @Injectable()
 export class ObjectToTreeService {
@@ -44,6 +45,7 @@ export class ObjectToTreeService {
               private _networkStepService : NetworkStepService,
               private _vpnStepService : VpnStepService,
               private _aaiService : AaiService,
+              private _featureFlagsService: FeatureFlagsService,
               private _store : NgRedux<AppState>) {
   }
 
@@ -54,10 +56,10 @@ export class ObjectToTreeService {
    * return all first optional first level of the model tree
    ************************************************************/
   getFirstLevelOptions(): ILevelNodeInfo[] {
-    return [new VnfModelInfo(this._dynamicInputsService, this._sharedTreeService, this._defaultDataGeneratorService, this._dialogService, this._vnfPopupService, this._vfModulePopupService, this._vfModuleUpgradePopupService,this._duplicateService, this._modalService, this._iframeService, this._componentInfoService, this._store)
-      , new NetworkModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._networkPopupService, this._duplicateService, this._modalService, this._iframeService,  this._store),
+    return [new VnfModelInfo(this._dynamicInputsService, this._sharedTreeService, this._defaultDataGeneratorService, this._dialogService, this._vnfPopupService, this._vfModulePopupService, this._vfModuleUpgradePopupService,this._duplicateService, this._modalService, this._iframeService, this._componentInfoService, this._featureFlagsService, this._store)
+      , new NetworkModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._networkPopupService, this._duplicateService, this._modalService, this._iframeService,  this._featureFlagsService, this._store),
       new PnfModelInfo(),
-      new VrfModelInfo(this._store, this._sharedTreeService, this._dialogService, this._iframeService, this._networkStepService, this._vpnStepService),
+      new VrfModelInfo(this._store, this._sharedTreeService, this._dialogService, this._iframeService, this._featureFlagsService, this._networkStepService, this._vpnStepService),
       new CollectionResourceModelInfo(this._store, this._sharedTreeService),
       new ConfigurationModelInfo(this._dynamicInputsService, this._sharedTreeService),
       new VnfGroupingModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._vnfGroupPopupService, this._iframeService, this._aaiService, this._store)];
index c56cc49..b8eddbb 100644 (file)
@@ -13,6 +13,7 @@ import {ModelInformationItem} from "../../../shared/components/model-information
 import {undoUpgradeService, upgradeService} from "../../../shared/storeUtil/utils/service/service.actions";
 import {VNFMethods} from "../../../shared/storeUtil/utils/vnf/vnf.actions";
 import {FeatureFlagsService, Features} from "../../../shared/services/featureFlag/feature-flags.service";
+import {Utils} from "../../../shared/utils/utils";
 
 @Injectable()
 export class SharedTreeService {
@@ -239,6 +240,16 @@ export class SharedTreeService {
     const mode = this._store.getState().global.drawingBoardStatus;
     return mode === DrawingBoardModes.EDIT || mode=== DrawingBoardModes.CREATE;
   }
+
+
+  isReachedToMaxInstances(properties, counter, flags): boolean{
+    let maxInstances  = Utils.getMaxFirstLevel(properties, flags);
+    if(_.isNil(maxInstances)){
+      return false;
+    }else {
+      return !(maxInstances > counter);
+    }
+  }
   /************************************************
    return number of instances with action Delete
    @type: vnfs networks, vngGroups (not vfModule)
index 5d4d165..c18b20d 100644 (file)
@@ -10,6 +10,7 @@ import * as _ from 'lodash';
 import {VfModule} from "../../../models/vfModule";
 import {VNFModel} from "../../../models/vnfModel";
 import {VnfGroupModel} from "../../../models/vnfGroupModel";
+import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.service";
 
 @Injectable()
 export class BasicPopupService {
@@ -29,17 +30,18 @@ export class BasicPopupService {
   }
 
   getModelFromResponse(result: any, modelType: string, modelName: string) {
+    let flags = FeatureFlagsService.getAllFlags(this._store);
     let rawModel = result[modelType][modelName];
     if (!rawModel) return;
     switch (modelType){
       case 'vnfs' : {
-        return new VNFModel(rawModel);
+        return new VNFModel(rawModel, flags);
       }
       case 'vfModules' : {
         return new VfModule(rawModel);
       }
       case 'networks' : {
-        return new NetworkModel(rawModel);
+        return new NetworkModel(rawModel, flags);
       }
       case 'vnfGroups' : {
         return new VnfGroupModel(rawModel);
index 03f118e..b4879a5 100644 (file)
@@ -2,29 +2,30 @@ import {
   Level1Model, Level1ModelProperties,
   Level1ModelResponseInterface
 } from "./nodeModel";
-import {VfcInstanceGroupMap} from "./vfcInstanceGroupMap";
+import {Utils} from "../utils/utils";
 
 
-export interface NetworkProperties extends Level1ModelProperties{
+export interface NetworkProperties extends Level1ModelProperties {
   ecomp_generated_naming: string;
   network_role: string;
 }
 
-export interface NetworkModelResponseInterface extends Level1ModelResponseInterface{
+export interface NetworkModelResponseInterface extends Level1ModelResponseInterface {
   properties: NetworkProperties;
 }
 
-export class NetworkModel extends Level1Model{
+export class NetworkModel extends Level1Model {
 
   roles: string[] = [];
   properties: NetworkProperties;
 
-  constructor(networkJson?: NetworkModelResponseInterface){
+  constructor(networkJson?: NetworkModelResponseInterface, flags?: { [key: string]: boolean }) {
     super(networkJson);
-    if(networkJson && networkJson.properties){
+    if (networkJson && networkJson.properties) {
       this.properties = networkJson.properties;
       // expecting network_role to be a comma-saparated list
       this.roles = networkJson.properties.network_role ? networkJson.properties.network_role.split(',') : [];
+      this.max = Utils.getMaxFirstLevel(this.properties, flags);
     }
   }
 
index 8389606..220dc0f 100644 (file)
@@ -3,25 +3,24 @@ import {
   Level1ModelProperties,
   Level1ModelResponseInterface
 } from "./nodeModel";
+import {Utils} from "../utils/utils";
 
-
-
-export interface VnfProperties extends Level1ModelProperties{
+export interface VnfProperties extends Level1ModelProperties {
   ecomp_generated_naming: string;
 }
 
-export interface VNFModelResponseInterface extends Level1ModelResponseInterface{
+export interface VNFModelResponseInterface extends Level1ModelResponseInterface {
   properties: VnfProperties;
 }
 
-export class VNFModel extends Level1Model{
+export class VNFModel extends Level1Model {
   properties: VnfProperties;
 
-  constructor(vnfJson?: VNFModelResponseInterface) {
+  constructor(vnfJson?: VNFModelResponseInterface, flags?: { [key: string]: boolean }) {
     super(vnfJson);
     if (vnfJson) {
       this.properties = vnfJson.properties;
+      this.max = Utils.getMaxFirstLevel(this.properties, flags);
     }
   }
-
 }
index 7e0575b..74fcd8f 100644 (file)
@@ -27,6 +27,14 @@ export class FeatureFlagsService {
     return FeatureFlagsService.getFlagState(flag, this.store);
   }
 
+  public getAllFlags():  { [key: string]: boolean}{
+    return this.store.getState().global.flags;
+  }
+
+  public static getAllFlags(store: NgRedux<AppState>):  { [key: string]: boolean}{
+    return store.getState().global.flags;
+  }
+
   /*static method for easy refactoring of code, so no injection of FeatureFlagsService is needed*/
   public static getFlagState(flag: Features, store: NgRedux<AppState>):boolean {
     let storeStateGlobalFields = store.getState().global;
index cb5e1a1..cd7ebdf 100644 (file)
@@ -2,6 +2,14 @@ import * as _ from 'lodash'
 
 export class Utils {
 
+  static getMaxFirstLevel(properties, flags: { [key: string]: boolean }) : number | null{
+    if (flags && !!flags['FLAG_2002_UNLIMITED_MAX']) {
+      return !_.isNil(properties) && !_.isNil(properties.max_instances) ? properties.max_instances : null;
+    } else {
+      return properties.max_instances || 1;
+    }
+  }
+
   public static clampNumber = (number, min, max) => {
     return Math.max(min, Math.min(number, max));
   };