aboutsummaryrefslogtreecommitdiffstats
path: root/vid-webpack-master/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'vid-webpack-master/src/app')
-rw-r--r--vid-webpack-master/src/app/app.routing.ts8
-rw-r--r--vid-webpack-master/src/app/drawingBoard/drawingBoard.routing.ts9
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts6
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts14
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts2
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.spec.ts254
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts100
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts4
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board.modes.ts3
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts17
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts108
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts232
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts8
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts2
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts48
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts80
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts22
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts39
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts4
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service.spec.ts4
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts2
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts2
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts53
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts10
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts8
-rw-r--r--vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts11
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html89
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.scss6
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts124
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts48
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts24
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts30
-rw-r--r--vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts45
-rw-r--r--vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html40
-rw-r--r--vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts74
-rw-r--r--vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts47
-rw-r--r--vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.spec.ts159
-rw-r--r--vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts50
-rw-r--r--vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts11
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.spec.ts37
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.ts78
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/networkGenerator/network.control.generator.spec.ts9
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/service.control.generator.spec.ts3
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts59
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts105
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts22
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts37
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator.spec.ts11
-rw-r--r--vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html5
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html28
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss2
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts142
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts5
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts3
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts8
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts3
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts30
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts31
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.spec.ts3
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.ts205
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service.ts95
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts201
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.spec.ts9
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.ts12
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service.spec.ts5
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html164
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss196
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts57
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts133
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts15
-rw-r--r--vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts51
-rw-r--r--vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts7
-rw-r--r--vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts12
-rw-r--r--vid-webpack-master/src/app/shared/models/networkModel.ts13
-rw-r--r--vid-webpack-master/src/app/shared/models/vfModule.ts5
-rw-r--r--vid-webpack-master/src/app/shared/models/vnfModel.ts13
-rw-r--r--vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts17
-rw-r--r--vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts43
-rw-r--r--vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.spec.ts66
-rw-r--r--vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.ts29
-rw-r--r--vid-webpack-master/src/app/shared/resolvers/viewEdit/viewEdit.resolver.ts3
-rw-r--r--vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.spec.ts19
-rw-r--r--vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.ts7
-rw-r--r--vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.spec.ts2
-rw-r--r--vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.ts7
-rw-r--r--vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts15
-rw-r--r--vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.spec.ts51
-rw-r--r--vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.ts27
-rw-r--r--vid-webpack-master/src/app/shared/shared.module.ts21
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/general/general.actions.ts12
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.spec.ts53
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.ts22
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/main.reducer.ts4
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.action.ts17
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.spec.ts18
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.ts20
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.actions.ts38
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.spec.ts468
-rw-r--r--vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.ts26
-rw-r--r--vid-webpack-master/src/app/shared/utils/constants.ts6
-rw-r--r--vid-webpack-master/src/app/shared/utils/util.spec.ts52
-rw-r--r--vid-webpack-master/src/app/shared/utils/utils.ts19
102 files changed, 3412 insertions, 1261 deletions
diff --git a/vid-webpack-master/src/app/app.routing.ts b/vid-webpack-master/src/app/app.routing.ts
index 779d17e3c..eaf4e9ca4 100644
--- a/vid-webpack-master/src/app/app.routing.ts
+++ b/vid-webpack-master/src/app/app.routing.ts
@@ -6,12 +6,20 @@ import {SupportComponent} from "./support/support.component";
import {HealthStatusRoutes} from "./healthStatus/health-status.routing";
import {VlanTaggingRoutes} from "./vlanTagging/vlan-tagging.routing";
import {InstantiationStatusRoutes} from "./instantiationStatus/InstantiationStatus.routing";
+import {InstantiationTemplatesModalComponent} from "./shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component";
const routes: Routes = [
...DrawingBoardRoutes,
...HealthStatusRoutes,
...VlanTaggingRoutes,
...InstantiationStatusRoutes,
{
+ path: 'instantiationTemplatesPopup',
+ component: InstantiationTemplatesModalComponent,
+ resolve: {
+ flags: FlagsResolve
+ }
+ },
+ {
path: 'servicePopup',
component: GenericFormPopupComponent,
resolve: {
diff --git a/vid-webpack-master/src/app/drawingBoard/drawingBoard.routing.ts b/vid-webpack-master/src/app/drawingBoard/drawingBoard.routing.ts
index 0c1fa700c..aebbdee5a 100644
--- a/vid-webpack-master/src/app/drawingBoard/drawingBoard.routing.ts
+++ b/vid-webpack-master/src/app/drawingBoard/drawingBoard.routing.ts
@@ -4,6 +4,7 @@ import {FlagsResolve} from "../shared/resolvers/flag/flag.resolver";
import {ViewEditResolver} from "../shared/resolvers/viewEdit/viewEdit.resolver";
import {DrawingBoardGuard} from "./guards/servicePlanningGuard/drawingBoardGuard";
import {RetryResolver} from "../shared/resolvers/retry/retry.resolver";
+import {RecreateResolver} from "../shared/resolvers/recreate/recreate.resolver";
export const DrawingBoardRoutes: Route[] = [
{
@@ -27,6 +28,14 @@ export const DrawingBoardRoutes: Route[] = [
}
},
{
+ path: 'RECREATE',
+ component: ServicePlanningComponent,
+ resolve: {
+ flags: FlagsResolve,
+ viewEditResolver: RecreateResolver
+ }
+ },
+ {
path: 'RETRY_EDIT',
component: ServicePlanningComponent,
resolve: {
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts
index 145ee19da..fb1172945 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts
@@ -28,6 +28,7 @@ import {DrawingBoardTreeComponent} from "../drawing-board-tree/drawing-board-tre
import {ComponentInfoModel} from "../component-info/component-info-model";
import {ComponentInfoService} from "../component-info/component-info.service";
import {FeatureFlagsService, Features} from "../../../shared/services/featureFlag/feature-flags.service";
+import {Utils} from "../../../shared/utils/utils";
@Component({
@@ -93,6 +94,7 @@ export class AvailableModelsTreeComponent {
service = {name: ''};
options: ITreeOptions = {
+ allowDrop:false,
nodeHeight: 36,
dropSlotHeight: 0,
nodeClass: (node: ITreeNode) => {
@@ -145,10 +147,10 @@ export class AvailableModelsTreeComponent {
this.isNewObject = isNewObject;
let data = node.data;
let dynamicInputs = data.dynamicInputs;
- let isAlaCarte: boolean = this.serviceHierarchy.service.vidNotions.instantiationType == 'ALaCarte';
+ let isAlaCarte: boolean = Utils.isALaCarte(this.serviceHierarchy.service.vidNotions.instantiationType);
let isEcompGeneratedNaming: boolean = data.isEcompGeneratedNaming;
let type: string = data.type;
- if (!this.store.getState().global.flags['FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD'] || node.data.type === ServiceNodeTypes.VF ||
+ if (node.data.type === ServiceNodeTypes.VF ||
this._availableModelsTreeService.shouldOpenDialog(type, dynamicInputs, isEcompGeneratedNaming)) {
this._iframeService.addClassOpenModal(this.parentElementClassName);
node.data.onAddClick(node, serviceId);
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts
index 7923313bf..8228f9531 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts
@@ -180,7 +180,7 @@ export class DrawingBoardHeader {
}
}
- extractOwningEntityNameAccordingtoId(id:String): string {
+ extractOwningEntityNameAccordingToId(id:String): string {
let owningEntityName;
_.forEach(this.store.getState().service.categoryParameters.owningEntityList,(owningEntity: OwningEntity) => {
if (owningEntity.id === id) {
@@ -190,12 +190,20 @@ export class DrawingBoardHeader {
return owningEntityName;
}
+ private extractSubscriberNameByGlobalSubscriberId(globalSubscriberId: string) {
+ return this.store.getState().service.subscribers.find(sub => sub.id === globalSubscriberId).name;
+ }
+
extractServiceFields(): any {
let instanceFields : ServiceInstance;
instanceFields = this.store.getState().service.serviceInstance[this.serviceModelId];
if (instanceFields.action === ServiceInstanceActions.Create) {
- instanceFields.subscriberName = this.store.getState().service.subscribers.find(sub => sub.id === instanceFields.globalSubscriberId).name;
- instanceFields.owningEntityName = this.extractOwningEntityNameAccordingtoId(instanceFields.owningEntityId);
+ if(_.isNil(instanceFields.subscriberName)) {
+ instanceFields.subscriberName = this.extractSubscriberNameByGlobalSubscriberId(instanceFields.globalSubscriberId);
+ }
+ if (_.isNil(instanceFields.owningEntityName)) {
+ instanceFields.owningEntityName = this.extractOwningEntityNameAccordingToId(instanceFields.owningEntityId);
+ }
}
return _.omit(instanceFields,['optionalGroupMembersMap', 'upgradedVFMSonsCounter', 'isUpgraded', 'latestAvailableVersion']);
}
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts
index 1b71d9098..634fa6271 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts
@@ -96,7 +96,7 @@ export class DrawingBoardHeaderService{
showEditService(mode: DrawingBoardModes, serviceModelId: string): boolean{
const serviceInstance = this.store.getState().service.serviceInstance;
- return mode === DrawingBoardModes.CREATE || ((mode === DrawingBoardModes.RETRY_EDIT || mode === DrawingBoardModes.EDIT)&&
+ return mode === DrawingBoardModes.CREATE || ((mode === DrawingBoardModes.RETRY_EDIT || mode === DrawingBoardModes.EDIT || mode === DrawingBoardModes.RECREATE )&&
!_.isNil(serviceInstance) && !_.isNil(serviceInstance[serviceModelId])&& serviceInstance[serviceModelId].action === ServiceInstanceActions.Create);
}
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.spec.ts
index 01ae898f5..425568b68 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.spec.ts
@@ -5,14 +5,15 @@ import {DragAndDropService} from "./dragAndDrop.service";
import {AppState} from "../../../../shared/store/reducers";
class MockAppStore<T> {
- dispatch(){
+ dispatch() {
}
+
getState() {
return {
global: {
flags: {
- "FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE" : true
+ "FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE": true
}
},
service: {
@@ -53,6 +54,7 @@ describe('Drag and drop service', () => {
let service: DragAndDropService;
let httpMock: HttpTestingController;
let store: NgRedux<AppState>;
+ let nodes;
beforeAll(done => (async () => {
TestBed.configureTestingModule({
@@ -67,158 +69,142 @@ describe('Drag and drop service', () => {
service = injector.get(DragAndDropService);
httpMock = injector.get(HttpTestingController);
store = injector.get(NgRedux);
+
+
})().then(done).catch(done.fail));
+ beforeEach(() => {
+ nodes = [
+ {
+ "trackById": "ckfqe3sb3y8",
+ "componentInfoType": "VNF",
+ "parentType": "",
+ "type": "VF",
+ "typeName": "VNF",
+ "instanceName": "2017-488_PASQUALE-vPE",
+ "id": "04686zg11ur2",
+ "children": [
+ {
+ "id": "1150884479608",
+ "action": "Create",
+ "instanceName": "puwesovabe",
+ "name": "puwesovabe",
+ "type": "VFmodule",
+ "trackById": "d5if1906rqa",
+ "parentType": "VNF",
+ "position": 1,
+ "componentInfoType": "VFModule",
+ "errors": {},
+ "updatePoistionFunction": () => {
+ },
+ },
+ {
+ "id": "4637423092446",
+ "action": "Create",
+ "instanceName": "bnmgtrx",
+ "name": "bnmgtrx",
+ "type": "VFmodule",
+ "trackById": "9ei9adlh27e",
+ "parentType": "VNF",
+ "position": 2,
+ "componentInfoType": "VFModule",
+ "updatePoistionFunction": () => {
+ }
+ }
+ ],
+ "errors": {},
+ }
+ ];
+ })
+ test('drag should execute array_move when the nodes parent are same', () => {
- test('drag should move element position', () => {
- let nodes = [{
- "modelCustomizationId": "91415b44-753d-494c-926a-456a9172bbb9",
- "modelId": "d6557200-ecf2-4641-8094-5393ae3aae60",
- "modelUniqueId": "91415b44-753d-494c-926a-456a9172bbb9",
- "missingData": false,
- "id": "tjjongy92jn",
- "action": "Create",
- "inMaint": false,
- "name": "yoav2_001",
- "modelName": "VF_vGeraldine 0",
- "type": "VF",
- "isEcompGeneratedNaming": true,
- "networkStoreKey": "VF_vGeraldine 0:0001",
- "vnfStoreKey": "VF_vGeraldine 0:0001",
- "typeName": "VNF",
- "menuActions": {"edit": {}, "showAuditInfo": {}, "duplicate": {}, "remove": {}, "delete": {}, "undoDelete": {}},
- "isFailed": false,
- "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, {
- "key": "Orch Status:",
- "testId": "orchStatus"
- }],
- "trackById": "di9khuolht",
- "parentType": "",
- "position": 0,
- "children": [{
- "modelCustomizationId": "f8c040f1-7e51-4a11-aca8-acf256cfd861",
- "modelId": "a27f5cfc-7f12-4f99-af08-0af9c3885c87",
- "modelUniqueId": "f8c040f1-7e51-4a11-aca8-acf256cfd861",
- "missingData": false,
- "id": 6654971919519,
- "action": "Create",
- "name": "VFModule1",
- "modelName": "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0",
- "type": "VFmodule",
- "isEcompGeneratedNaming": true,
- "dynamicInputs": [],
- "dynamicModelName": "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0bykqx",
- "typeName": "M",
- "menuActions": {"edit": {}, "showAuditInfo": {}, "remove": {}, "delete": {}, "undoDelete": {}},
- "isFailed": false,
- "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, {
- "key": "Orch Status:",
- "testId": "orchStatus"
- }],
- "trackById": "5pfyfah820h",
- "parentType": "VNF",
- "position": 0,
- "errors": {}
- }, {
- "modelCustomizationId": "6add59e0-7fe1-4bc4-af48-f8812422ae7c",
- "modelId": "41708296-e443-4c71-953f-d9a010f059e1",
- "modelUniqueId": "6add59e0-7fe1-4bc4-af48-f8812422ae7c",
- "missingData": false,
- "id": 987761655742,
- "action": "Create",
- "name": "VNFModule3",
- "modelName": "vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2",
- "type": "VFmodule",
- "isEcompGeneratedNaming": true,
- "dynamicInputs": [],
- "dynamicModelName": "vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2fjrrc",
- "typeName": "M",
- "menuActions": {"edit": {}, "showAuditInfo": {}, "remove": {}, "delete": {}, "undoDelete": {}},
- "isFailed": false,
- "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, {
- "key": "Orch Status:",
- "testId": "orchStatus"
- }],
- "trackById": "i3dllio31bb",
- "parentType": "VNF",
- "position": 1,
- "errors": {}
- }, {
- "modelCustomizationId": "55b1be94-671a-403e-a26c-667e9c47d091",
- "modelId": "522159d5-d6e0-4c2a-aa44-5a542a12a830",
- "modelUniqueId": "55b1be94-671a-403e-a26c-667e9c47d091",
- "missingData": false,
- "id": 873798901625,
- "action": "Create",
- "name": "VFModule2",
- "modelName": "vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1",
- "type": "VFmodule",
- "isEcompGeneratedNaming": true,
- "dynamicInputs": [],
- "dynamicModelName": "vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1djjni",
- "typeName": "M",
- "menuActions": {"edit": {}, "showAuditInfo": {}, "remove": {}, "delete": {}, "undoDelete": {}},
- "isFailed": false,
- "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, {
- "key": "Orch Status:",
- "testId": "orchStatus"
- }],
- "trackById": "w7bvw1nh47s",
- "parentType": "VNF",
- "position": 2,
- "errors": {}
- }],
- "errors": {}
- }, {
- "modelCustomizationId": "91415b44-753d-494c-926a-456a9172bbb9",
- "modelId": "d6557200-ecf2-4641-8094-5393ae3aae60",
- "modelUniqueId": "91415b44-753d-494c-926a-456a9172bbb9",
- "missingData": false,
- "id": "dywch8hkomi",
- "action": "Create",
- "inMaint": false,
- "name": "yoav2",
- "modelName": "VF_vGeraldine 0",
- "type": "VF",
- "isEcompGeneratedNaming": true,
- "networkStoreKey": "VF_vGeraldine 0",
- "vnfStoreKey": "VF_vGeraldine 0",
- "typeName": "VNF",
- "menuActions": {"edit": {}, "showAuditInfo": {}, "duplicate": {}, "remove": {}, "delete": {}, "undoDelete": {}},
- "isFailed": false,
- "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, {
- "key": "Orch Status:",
- "testId": "orchStatus"
- }],
- "trackById": "fjczf1urdqo",
- "parentType": "",
- "position": 1,
- "children": [],
- "errors": {}
- }];
let from = {
+ id: "04686zg11ur2",
+ index: 0,
data: {
- type: 'VF',
- index: 1
+ instanceName: 'puwesovabe',
+ },
+ parent: {
+ data: {
+ type: 'VF',
+ index: 0,
+ trackById: 'ckfqe3sb3y8',
+ vnfStoreKey: '2017-488_PASQUALE-vPE 0',
+ }
}
};
let to = {
parent: {
+ id: "4637423092446",
+ index: 1,
data: {
- type: 'VF',
- index: 0
+ instanceName: 'bnmgtrx',
+ },
+ parent: {
+ data: {
+ type: 'VF',
+ trackById: 'ckfqe3sb3y8',
+ vnfStoreKey: '2017-488_PASQUALE-vPE 0',
+ }
}
}
};
- jest.spyOn(service, 'array_move');
- service.drag(store, "serviceInstanceId", nodes, {from, to});
+ jest.spyOn(service, 'array_move');
+ service.drop(store, "serviceInstanceId", nodes, {from, to});
expect(service.array_move).toHaveBeenCalled();
});
+ test('drag shouldnt execute array_move when the nodes parent are different', () => {
+
+ let from = {
+ id: 1150884479608,
+ index: 0,
+ data: {
+ instanceName: '2017-488_PASQUALE-vPE',
+ },
+ parent: {}
+ };
+
+ let to = {
+ parent: {
+ id: 4637423092446,
+ index: 1,
+ data: {
+ instanceName: 'bnmgtrx',
+ },
+ parent: {
+ data: {
+ type: 'VF',
+ trackById: '1111',
+ vnfStoreKey: '2017-488_PASQUALE-vPE 0',
+ }
+ }
+ }
+ };
+
+
+ jest.spyOn(service, 'array_move');
+
+ service.drop(store, "serviceInstanceId", nodes, {from, to});
+
+ jest.clearAllMocks();
+
+ expect(service.array_move).not.toHaveBeenCalled();
+
+ });
+
+ test('drop should change nodes index and position', () => {
+
+ let arr: Array<any> = service.array_move(nodes[0].children, 0, 1, "serviceInstanceId", '')
+
+ expect(arr[0]).toMatchObject({instanceName: "bnmgtrx", position: 1});
+ expect(arr[1]).toMatchObject({instanceName: "puwesovabe", position: 2});
+
+ });
});
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts
index 15da89ad3..96e50178b 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts
@@ -8,11 +8,29 @@ import * as _ from 'lodash';
@Injectable()
export class DragAndDropService {
- constructor(private store: NgRedux<AppState>){}
+ constructor(private store: NgRedux<AppState>) {
+ }
- isAllow(): boolean {
+ isFlagOn(): boolean {
return FeatureFlagsService.getFlagState(Features.FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE, this.store);
}
+
+
+ /***********************************************************************************************
+ if the falg is ON and nodes have same parent
+ ***********************************************************************************************/
+ isAllowDrop(from: any, to: any): boolean {
+ return this.isFlagOn() && this.isSameParent(from, to);
+ }
+
+ private isSameParent(from: any, to: any): boolean {
+ try {
+ return from.parent.data.trackById === to.parent.parent.data.trackById;
+ } catch (e) { //parent not found
+ return false;
+ }
+ }
+
/********************************************************************
* manage drawing-board drag and drop operation
* @param nodes - array with elements data.
@@ -22,57 +40,67 @@ export class DragAndDropService {
* @param to - element to information
************************************************************/
- drag(store, instanceId : string , nodes, {from, to}) :void{
- if (!store.getState().global.flags["FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE"]) return;
+ drop(store, instanceId: string, nodes, {from, to}): void {
+
+ if (!this.isFlagOn()) return;
- let firstLevelNames : DragAndDropModel[] = [
+ if (this.isAllowDrop(from, to)) {
+ let vfModules = nodes.find((parent) => {
+ return parent.trackById === to.parent.parent.data.trackById;
+ }).children;
+ this.array_move(vfModules, from.index, to.parent.index, instanceId, to.parent.parent.data.vnfStoreKey);
+ }
+
+ /* let firstLevelNames : DragAndDropModel[] = [
new DragAndDropModel('VF',true),
new DragAndDropModel('VL',true),
new DragAndDropModel('VFmodule',false)
- ];
-
- const fromObject = _.find(firstLevelNames, ['type', from.data.type]);
- const toObject = _.find(firstLevelNames, ['type', to.parent.data.type]);
-
- /***********************************************************************************************
- if the type are the same and there in same level + same parent -> then change element position
- ***********************************************************************************************/
- if(fromObject.isFirstLevel === toObject.isFirstLevel){ // moving element in the same level and in the first level
- if(fromObject.isFirstLevel){
- this.array_move(nodes, from.index , to.parent.index, instanceId);
- } else if(fromObject.isFirstLevel === toObject.isFirstLevel){
- /* check if they have the same parent */
- if(from.parent.data.trackById === to.parent.parent.data.trackById){
- let vfModules = nodes.find((parents)=> {
- return parents.trackById === to.parent.parent.data.trackById;
- }).children;
- this.array_move(vfModules, from.index , to.parent.index, instanceId, to.parent.parent.data.vnfStoreKey);
+ ];
+
+ const fromObject = _.find(firstLevelNames, ['type', from.data.type]);
+ const toObject = _.find(firstLevelNames, ['type', to.parent.data.type]);
+
+ /!***********************************************************************************************
+ if the type are the same and there in same level + same parent -> then change element position
+ ***********************************************************************************************!/
+ if(fromObject.isFirstLevel === toObject.isFirstLevel){ // moving element in the same level and in the first level
+ if(fromObject.isFirstLevel){
+ this.array_move(nodes, from.index , to.parent.index, instanceId);
+ } else if(fromObject.isFirstLevel === toObject.isFirstLevel){
+ /!* check if they have the same parent *!/
+ if(from.parent.data.trackById === to.parent.parent.data.trackById){
+ let vfModules = nodes.find((parents)=> {
+ return parents.trackById === to.parent.parent.data.trackById;
+ }).children;
+ this.array_move(vfModules, from.index , to.parent.index, instanceId, to.parent.parent.data.vnfStoreKey);
+ }
}
- }
- }
+ }*/
}
- /********************************************************************
+ /********************************************************************
* move element inside array with elements position
* @param arr - array with elements data.
* @param originalPosition - element original position
* @param destPosition - element dest position
* @param destPinstanceIdosition - instance id
******************************************************************/
- array_move(arr, originalPosition, destPosition, instanceId : string, parentStoreKey?) {
- if (destPosition >= arr.length) {
- let k = destPosition - arr.length + 1;
- while (k--) {
- arr.push(undefined);
- }
- }
- arr.splice(destPosition, 0, arr.splice(originalPosition, 1)[0]);
+ array_move(arr, originalPosition, destPosition, instanceId: string, parentStoreKey?): Array<any> {
+
+ let moved_node = arr[originalPosition]
+
+ arr.splice(originalPosition, 1);
+
+ arr.splice(destPosition, 0, moved_node);
+
arr.forEach((item, index) => {
- if(item.position !== index){
- item.position = index;
+ if (item.position !== index + 1) {
+ item.position = index + 1;
item.updatePoistionFunction(this, item, instanceId, parentStoreKey);
}
});
+
+ return arr;
};
}
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts
index 0e2d8e276..f3542573d 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts
@@ -127,11 +127,11 @@ export class DrawingBoardTreeComponent implements OnInit, AfterViewInit {
nodes = [];
serviceModelId: string;
options = {
- allowDrag: this._dragAndDropService.isAllow(),
+ allowDrag: this._dragAndDropService.isFlagOn(),
actionMapping: {
mouse: {
drop: (tree:TreeModel, node:TreeNode, $event:any, {from, to}) => {
- this._dragAndDropService.drag(this.store, this.serviceModelId, this.nodes, {from, to});
+ this._dragAndDropService.drop(this.store, this.serviceModelId, this.nodes, {from, to});
}
}
},
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board.modes.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board.modes.ts
index 452666f91..78e2b629e 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board.modes.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board.modes.ts
@@ -4,5 +4,6 @@ export enum DrawingBoardModes {
VIEW = 'VIEW',
EDIT = 'EDIT',
OLD_VIEW_EDIT = 'OLD_VIEW_EDIT',
- CREATE = 'CREATE'
+ CREATE = 'CREATE',
+ RECREATE = 'RECREATE'
}
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts
index 3483885b5..50bfa936e 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts
@@ -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));
@@ -418,6 +428,11 @@ describe('Drawing board tree service', () => {
}
}
+ },
+ global : {
+ flags : {
+
+ }
}
}
}
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts
index 5fb5f0b15..847790de9 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts
@@ -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++;
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts
index 10c13661f..089f812a7 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts
@@ -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",
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts
index 3ed40cd5f..3ba4a2c4b 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts
@@ -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)
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts
index 840f31dcf..a44c21bf0 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts
@@ -13,6 +13,7 @@ import {VnfPopupService} from "../../../../../shared/components/genericFormPopup
import {DuplicateService} from "../../../duplicate/duplicate.service";
import {IframeService} from "../../../../../shared/utils/iframe.service";
import {RelatedVnfMemberInfoModel} from "./relatedVnfMember.info.model";
+import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
class MockAppStore<T> {
@@ -38,6 +39,7 @@ describe('Related Vnf member Model Info', () => {
DynamicInputsService,
DialogService,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
VnfPopupService,
DefaultDataGeneratorService,
SharedTreeService,
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts
index b596d0b48..276c0aeb2 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts
@@ -16,6 +16,9 @@ import {ModelInformationItem} from "../../../../../shared/components/model-infor
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";
+import {instance, mock, when} from "ts-mockito";
+import each from "jest-each";
class MockAppStore<T> {
getState() {
@@ -27,6 +30,12 @@ class MockAppStore<T> {
}
}
+class MockFeatureFlagsService extends FeatureFlagsService{
+ getAllFlags(): { [p: string]: boolean } {
+ return {};
+ }
+}
+
describe('VFModule Model Info', () => {
let injector;
let _dynamicInputsService : DynamicInputsService;
@@ -34,8 +43,12 @@ describe('VFModule Model Info', () => {
let vfModuleModel: VFModuleModelInfo;
let _dialogService : DialogService;
let _vfModulePopupService : VfModulePopuopService;
+ let _vfModuleUpgradePopupService : VfModuleUpgradePopupService;
let _iframeService : IframeService;
let _componentInfoService : ComponentInfoService;
+ let mockFeatureFlagsService: FeatureFlagsService = mock(FeatureFlagsService);
+ let mockFeatureFlagsServiceInstance: FeatureFlagsService = instance(mockFeatureFlagsService);
+
beforeAll(done => (async () => {
TestBed.configureTestingModule({
@@ -44,6 +57,7 @@ describe('VFModule Model Info', () => {
DynamicInputsService,
DialogService,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
SharedTreeService,
IframeService,
{provide: NgRedux, useClass: MockAppStore},
@@ -51,7 +65,7 @@ describe('VFModule Model Info', () => {
AaiService,
HttpClient,
HttpHandler,
- FeatureFlagsService,
+ {provide: FeatureFlagsService, useValue: mockFeatureFlagsServiceInstance},
ComponentInfoService
]
});
@@ -59,8 +73,9 @@ describe('VFModule Model Info', () => {
injector = getTestBed();
_sharedTreeService = injector.get(SharedTreeService);
- _componentInfoService = injector.get(ComponentInfoService)
- vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _iframeService, MockNgRedux.getInstance(),_componentInfoService);
+ _componentInfoService = injector.get(ComponentInfoService);
+ vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _vfModuleUpgradePopupService,
+ _iframeService, mockFeatureFlagsServiceInstance, MockNgRedux.getInstance(),_componentInfoService);
})().then(done).catch(done.fail));
@@ -468,6 +483,33 @@ describe('VFModule Model Info', () => {
expect(actualVNFInfo).toEqual(expectedVNFInfo);
});
+ each([
+ ["maxCountInstances 3, currentNodeCount 1, flag on",{maxCountInstances:3}, 1, {FLAG_2002_UNLIMITED_MAX: true}, false],
+ ["maxCountInstances 3, currentNodeCount 3, flag on",{maxCountInstances:3}, 3, {FLAG_2002_UNLIMITED_MAX: true}, true],
+ ["no maxCountInstances, currentNodeCount 0, flag off",{}, 0, {FLAG_2002_UNLIMITED_MAX: false}, false],
+ ["no maxCountInstances, currentNodeCount 1, flag off",{}, 1, {FLAG_2002_UNLIMITED_MAX: false}, true],
+ ["no maxCountInstances, currentNodeCount 1, no flags",{}, 1, null, true],
+ ["no maxCountInstances, currentNodeCount 0, flag on",{}, 0, {FLAG_2002_UNLIMITED_MAX: true}, false],
+ ["no maxCountInstances, currentNodeCount 1, flag on",{}, 1, {FLAG_2002_UNLIMITED_MAX: true}, false],
+ ["no maxCountInstances, currentNodeCount 1000, flag on",{}, 1000, {FLAG_2002_UNLIMITED_MAX: true}, false],
+ ]).test('isVFModuleReachedLimit: %s', (desc, properties, currentNodeCount, flags, expected) => {
+
+ const node = { data: {
+ name : 'vfModuleName'
+ }};
+
+ const serviceHierarchy = {
+ servicedId :{
+ vfModules : {
+ vfModuleName : {
+ properties
+ }}}};
+
+ when(mockFeatureFlagsService.getAllFlags()).thenReturn(flags);
+
+ expect(vfModuleModel.isVFModuleReachedLimit(node, serviceHierarchy, 'servicedId', currentNodeCount)).toEqual(expected);
+ });
+
function getVFModule(){
return {
"uuid":"522159d5-d6e0-4c2a-aa44-5a542a12a830",
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts
index 47a6dcb50..1ce452793 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts
@@ -8,10 +8,7 @@ import {VfModuleInstance} from "../../../../../shared/models/vfModuleInstance";
import {VfModule} from "../../../../../shared/models/vfModule";
import {NgRedux} from "@angular-redux/store";
import {ITreeNode} from "angular-tree-component/dist/defs/api";
-import {
- GenericFormPopupComponent,
- PopupType
-} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
+import {GenericFormPopupComponent, PopupType} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
import {DialogService} from "ng2-bootstrap-modal";
import {VfModulePopuopService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service";
import {AppState} from "../../../../../shared/store/reducers";
@@ -19,24 +16,22 @@ import {MessageBoxData} from "../../../../../shared/components/messageBox/messag
import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service";
import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service";
import {IframeService} from "../../../../../shared/utils/iframe.service";
-import {
- deleteActionVfModuleInstance,
- removeVfModuleInstance,
- undoDeleteVfModuleInstance,
- undoUgradeVFModule,
- updateVFModulePosition,
- upgradeVFModule
-} from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions";
+import {deleteActionVfModuleInstance, deleteVFModuleField, removeVfModuleInstance, undoDeleteVfModuleInstance, undoUgradeVFModule, updateVFModulePosition, upgradeVFModule} from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions";
import {ComponentInfoService} from "../../../component-info/component-info.service";
import {ComponentInfoType} from "../../../component-info/component-info-model";
import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
+import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
+import {FeatureFlagsService, Features} from "../../../../../shared/services/featureFlag/feature-flags.service";
+import {Utils} from "../../../../../shared/utils/utils";
export class VFModuleModelInfo implements ILevelNodeInfo {
constructor(private _dynamicInputsService: DynamicInputsService,
private _sharedTreeService: SharedTreeService,
private _dialogService: DialogService,
private _vfModulePopupService: VfModulePopuopService,
+ private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
private _iframeService: IframeService,
+ private _featureFlagsService: FeatureFlagsService,
private _store: NgRedux<AppState>,
private _componentInfoService: ComponentInfoService) {
}
@@ -93,7 +88,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
newVfModule.typeName = this.typeName;
newVfModule.menuActions = this.getMenuAction(<any>newVfModule, currentModel.uuid);
newVfModule.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
- newVfModule.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage: "";
+ newVfModule.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
newVfModule = this._sharedTreeService.addingStatusProperty(newVfModule);
return newVfModule;
@@ -247,7 +242,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
if (!_.isNil(this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF]) && node.parent.data.name === this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF].originalName) {
const existingVFModules = this.getCountVFModuleOfSelectedVNF(node, selectedVNF, serviceModelId);
const reachedLimit = this.isVFModuleReachedLimit(node, this._store.getState().service.serviceHierarchy, serviceModelId, existingVFModules);
- const showAddIcon = this._sharedTreeService.shouldShowAddIcon()&& !reachedLimit;
+ const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !reachedLimit;
return new AvailableNodeIcons(showAddIcon, reachedLimit);
}
return new AvailableNodeIcons(false, false);
@@ -297,13 +292,16 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
}
isVFModuleReachedLimit(node: any, serviceHierarchy: any, serviceModelId: string, currentNodeCount: number): boolean {
- let maxNodes: number = 1;
+ const flags = this._featureFlagsService.getAllFlags();
let vnfModules = serviceHierarchy[serviceModelId].vfModules;
- if (vnfModules[node.data.name]) {
- maxNodes = vnfModules[node.data.name].properties.maxCountInstances || 1;
+ const maxInstances = vnfModules[node.data.name]
+ ? Utils.getMaxVfModule(vnfModules[node.data.name].properties, flags)
+ : null;
+ if (_.isNil(maxInstances)) {
+ return false;
}
- return !(maxNodes > currentNodeCount);
+ return !(maxInstances > currentNodeCount);
}
getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } {
@@ -351,15 +349,15 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
},
undoDelete: {
method: (node, serviceModelId) => {
- this._store.dispatch(undoDeleteVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId))
+ this._store.dispatch(undoDeleteVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId));
+ this._store.dispatch(deleteVFModuleField(node.data.modelName, node.parent.data.vnfStoreKey, node.data.servicedId ,node.data.dynamicModelName, 'retainAssignments'));
},
visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node),
enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
},
- upgrade : {
- method : (node, serviceModelId) => {
- this._sharedTreeService.upgradeBottomUp(node, serviceModelId);
- this._store.dispatch(upgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName));
+ upgrade: {
+ method: (node, serviceModelId) => {
+ this.upgradeVFM(serviceModelId, node);
},
visible: (node,serviceModelId) => {
return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
@@ -371,7 +369,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
undoUpgrade: {
method: (node, serviceModelId) => {
this._sharedTreeService.undoUpgradeBottomUp(node, serviceModelId);
- this._store.dispatch(undoUgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName));
+ this._store.dispatch(undoUgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName));
},
visible: (node) => {
return this._sharedTreeService.shouldShowUndoUpgrade(node);
@@ -383,7 +381,31 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
};
}
- updatePosition(that , node, instanceId, parentStoreKey): void {
+ private upgradeVFM(serviceModelId, node) {
+ if (FeatureFlagsService.getFlagState(Features.FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, this._store)) {
+ this._iframeService.addClassOpenModal('content');
+ this._dialogService.addDialog(GenericFormPopupComponent, {
+ type: PopupType.VF_MODULE_UPGRADE,
+ uuidData: <any>{
+ serviceId: serviceModelId,
+ modelName: node.data.modelName,
+ vFModuleStoreKey: node.data.dynamicModelName,
+ vnfStoreKey: node.parent.data.vnfStoreKey,
+ modelId: node.data.modelId,
+ type: node.data.type,
+ popupService: this._vfModuleUpgradePopupService,
+ vfModule : _.cloneDeep(node)
+ },
+ node,
+ isUpdateMode: false
+ });
+ }else {
+ this._sharedTreeService.upgradeBottomUp(node, serviceModelId);
+ this._store.dispatch(upgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId ,node.data.dynamicModelName));
+ }
+ }
+
+ updatePosition(that, node, instanceId, parentStoreKey): void {
that.store.dispatch(updateVFModulePosition(node, instanceId, parentStoreKey));
}
@@ -395,12 +417,12 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
getInfo(model, instance): ModelInformationItem[] {
const modelInformation = !_.isEmpty(model) && !_.isEmpty(model.properties) ? [
ModelInformationItem.createInstance("Base module", model.properties.baseModule),
- ModelInformationItem.createInstance("Min instances", !_.isNull(model.properties.minCountInstances)? String(model.properties.minCountInstances): null),
- ModelInformationItem.createInstance("Max instances", !_.isNull(model.properties.maxCountInstances)? String(model.properties.maxCountInstances): null),
- ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.properties.initialCount)? String(model.properties.initialCount): null)
+ ModelInformationItem.createInstance("Min instances", !_.isNull(model.properties.minCountInstances) ? String(model.properties.minCountInstances) : null),
+ ModelInformationItem.createInstance("Max instances", !_.isNull(model.properties.maxCountInstances) ? String(model.properties.maxCountInstances) : null),
+ ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.properties.initialCount) ? String(model.properties.initialCount) : null)
] : [];
- const instanceInfo = [];
+ const instanceInfo = [];
const result = [modelInformation, instanceInfo];
return _.uniq(_.flatten(result));
}
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts
index de8962787..3ac6076dc 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts
@@ -22,6 +22,13 @@ import {ComponentInfoService} from "../../../component-info/component-info.servi
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;
@@ -32,10 +39,12 @@ describe('Vnf Model Info', () => {
let _defaultDataGeneratorService : DefaultDataGeneratorService;
let _dialogService : DialogService;
let _vfModulePopupService : VfModulePopuopService;
+ let _vfModuleUpgradePopupService : VfModuleUpgradePopupService;
let _vnfPopupService : VnfPopupService;
let _duplicateService : DuplicateService;
let _iframeService : IframeService;
let _componentInfoService : ComponentInfoService;
+ let _featureFlagsService : FeatureFlagsService;
let _store : NgRedux<AppState>;
let vnfModel: VnfModelInfo;
@@ -47,6 +56,7 @@ describe('Vnf Model Info', () => {
DynamicInputsService,
DialogService,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
VnfPopupService,
DefaultDataGeneratorService,
SharedTreeService,
@@ -54,7 +64,7 @@ describe('Vnf Model Info', () => {
AaiService,
HttpClient,
HttpHandler,
- FeatureFlagsService,
+ {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
ComponentInfoService,
IframeService]
}).compileComponents();
@@ -62,7 +72,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,
@@ -71,10 +81,12 @@ describe('Vnf Model Info', () => {
_dialogService,
_vnfPopupService,
_vfModulePopupService,
+ _vfModuleUpgradePopupService,
_duplicateService,
null,
_iframeService,
_componentInfoService,
+ _featureFlagsService,
_store);
@@ -456,6 +468,12 @@ describe('Vnf Model Info', () => {
expect(actualVNFInfo).toEqual(expectedVNFInfo);
});
+ test('When there is no max Max instances text is: Unlimited (default)', () => {
+ let actualVNFInfo = vnfModel.getInfo({just:"not empty"},null);
+ const maxInstancesItem = actualVNFInfo.find((item)=> item.label == 'Max instances');
+ expect(maxInstancesItem.values[0]).toEqual('Unlimited (default)');
+ });
+
function getVNFModel(){
return {
"name":"VF_vGeraldine",
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts
index ebcba162e..ff86925f1 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts
@@ -9,10 +9,7 @@ import {SharedTreeService} from "../../shared.tree.service";
import {NgRedux} from "@angular-redux/store";
import {AppState} from "../../../../../shared/store/reducers";
import {DefaultDataGeneratorService} from "../../../../../shared/services/defaultDataServiceGenerator/default.data.generator.service";
-import {
- GenericFormPopupComponent,
- PopupType
-} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
+import {GenericFormPopupComponent, PopupType} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
import {DialogService} from 'ng2-bootstrap-modal';
import {VnfPopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service";
import {VfModulePopuopService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service";
@@ -26,18 +23,15 @@ import {changeInstanceCounter, removeInstance} from "../../../../../shared/store
import {MessageBoxData} from "../../../../../shared/components/messageBox/messageBox.data";
import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service";
import {ServiceInstanceActions} from "../../../../../shared/models/serviceInstanceActions";
-import {
- deleteActionVnfInstance,
- undoDeleteActionVnfInstance,
- undoUpgradeVnf,
- updateVnfPosition,
- upgradeVnf
-} from "../../../../../shared/storeUtil/utils/vnf/vnf.actions";
+import {deleteActionVnfInstance, undoDeleteActionVnfInstance, undoUpgradeVnf, updateVnfPosition, upgradeVnf} from "../../../../../shared/storeUtil/utils/vnf/vnf.actions";
import * as _ from 'lodash';
import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
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";
+import {Constants} from "../../../../../shared/utils/constants";
export class VnfModelInfo implements ILevelNodeInfo {
constructor(private _dynamicInputsService: DynamicInputsService,
@@ -46,10 +40,12 @@ export class VnfModelInfo implements ILevelNodeInfo {
private _dialogService: DialogService,
private _vnfPopupService: VnfPopupService,
private _vfModulePopupService: VfModulePopuopService,
+ private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
private _duplicateService: DuplicateService,
private modalService: SdcUiServices.ModalService,
private _iframeService: IframeService,
private _componentInfoService: ComponentInfoService,
+ private _featureFlagsService: FeatureFlagsService,
private _store: NgRedux<AppState>) {
}
@@ -85,7 +81,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());
};
@@ -102,7 +98,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;
};
@@ -111,7 +107,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._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);
};
/***********************************************************
@@ -179,8 +175,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)
}
@@ -209,9 +205,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)
},
@@ -322,8 +318,9 @@ 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", !_.isNil(model.min) ? String(model.min) : null),
+ ModelInformationItem.createInstance("Max instances", !_.isNil(model.max) ? String(model.max) :
+ Constants.ModelInfo.UNLIMITED_DEFAULT)
] : [];
const instanceInfo = !_.isEmpty(instance) ? [
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts
index 4c779a313..3dbc60adb 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts
@@ -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);
}
}
};
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service.spec.ts
index c7c8d07a0..6ad640317 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service.spec.ts
@@ -84,7 +84,6 @@ describe('Network step service', () => {
"genericModalCriteria": {"roles": ["-- select an option --", "network role 1", "network role 2", "network role 3", "network role 4", "network role 5"]},
"name": null,
"flags": {
- "CREATE_INSTANCE_TEST": false,
"EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false,
"FLAG_ENABLE_WEBPACK_MODERN_UI": true,
@@ -95,12 +94,9 @@ describe('Network step service', () => {
"FLAG_SHOW_ASSIGNMENTS": true,
"FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true,
"FLAG_DUPLICATE_VNF": true,
- "FLAG_DEFAULT_VNF": true,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true,
"FLAG_A_LA_CARTE_AUDIT_INFO": true,
"FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true,
"FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true,
- "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true,
"FLAG_1902_NEW_VIEW_EDIT": true,
"FLAG_VF_MODULE_RESUME_STATUS_CREATE": true,
"FLAG_1906_COMPONENT_INFO": true
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts
index 7ab2f5b5b..9add349db 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts
@@ -32,6 +32,7 @@ import {ErrorMsgService} from "../../../../shared/components/error-msg/error-msg
import {ComponentInfoService} from "../../component-info/component-info.service";
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";
class MockAppStore<T> {
getState() {
@@ -73,6 +74,7 @@ describe('Model Tree Generator service', () => {
NetworkPopupService,
NetworkControlGenerator,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
VfModuleControlGenerator,
VnfGroupControlGenerator,
DialogService,
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts
index 7246adc27..e5559ee15 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts
@@ -35,6 +35,7 @@ import {ComponentInfoService} from "../../component-info/component-info.service"
import {IModelTreeNodeModel} from "../../../objectsToTree/objectToModelTree/modelTreeNode.model";
import {VpnStepService} from "../models/vrf/vrfModal/vpnStep/vpn.step.service";
import {NetworkStepService} from "../models/vrf/vrfModal/networkStep/network.step.service";
+import {VfModuleUpgradePopupService} from "../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
class MockAppStore<T> {
getState() {
@@ -98,6 +99,7 @@ describe('Model Tree Generator service', () => {
NetworkPopupService,
NetworkControlGenerator,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
VfModuleControlGenerator,
VnfGroupControlGenerator,
DialogService,
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts
index c101f44e9..75ae1e149 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts
@@ -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;
}
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts
index 0072196f2..1e6825130 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts
@@ -24,6 +24,8 @@ import {AaiService} from "../../../shared/services/aaiService/aai.service";
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 {
@@ -34,6 +36,7 @@ export class ObjectToTreeService {
private _vnfPopupService : VnfPopupService,
private _networkPopupService : NetworkPopupService,
private _vfModulePopupService : VfModulePopuopService,
+ private _vfModuleUpgradePopupService : VfModuleUpgradePopupService,
private _vnfGroupPopupService : VnfGroupPopupService,
private _duplicateService : DuplicateService,
private _modalService: SdcUiServices.ModalService,
@@ -42,6 +45,7 @@ export class ObjectToTreeService {
private _networkStepService : NetworkStepService,
private _vpnStepService : VpnStepService,
private _aaiService : AaiService,
+ private _featureFlagsService: FeatureFlagsService,
private _store : NgRedux<AppState>) {
}
@@ -52,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._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)];
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts
index 89e20a2d6..b330b72dc 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts
@@ -40,6 +40,7 @@ import {ComponentInfoModel, ComponentInfoType} from "../component-info/component
import {ModelInformationItem} from "../../../shared/components/model-information/model-information.component";
import {VpnStepService} from "./models/vrf/vrfModal/vpnStep/vpn.step.service";
import {NetworkStepService} from "./models/vrf/vrfModal/networkStep/network.step.service";
+import {VfModuleUpgradePopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
class MockAppStore<T> {
getState() {
@@ -96,6 +97,7 @@ describe('Shared Tree Service', () => {
NetworkPopupService,
NetworkControlGenerator,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
VfModuleControlGenerator,
VnfGroupControlGenerator,
DialogService,
@@ -162,7 +164,7 @@ describe('Shared Tree Service', () => {
jest.spyOn(AuditInfoModalComponent.openInstanceAuditInfoModal, 'next');
let modelInfoServiceMock: ILevelNodeInfo = new VnfModelInfo(null, null,
- null, null, null, null,
+ null, null, null, null, null,
null, null, null, null,null);
const modelMock = {"a": "a"};
const instanceMock = {"instance": "instance", "trackById": "123456789"};
@@ -465,19 +467,15 @@ function getStore() {
"global": {
"name": null,
"flags": {
- "CREATE_INSTANCE_TEST": false,
"EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true,
"FLAG_SERVICE_MODEL_CACHE": true,
"FLAG_SHOW_ASSIGNMENTS": true,
"FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true,
- "FLAG_DEFAULT_VNF": true,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true,
"FLAG_A_LA_CARTE_AUDIT_INFO": true,
"FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true,
"FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true,
- "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true,
"FLAG_1902_NEW_VIEW_EDIT": true,
"FLAG_1810_IDENTIFY_SERVICE_FOR_NEW_UI": false,
"FLAG_1902_VNF_GROUPING": true,
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts
index c56cc4999..b8eddbbf7 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts
@@ -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)
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html
index 212981aaf..16b8c0132 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html
@@ -16,6 +16,13 @@
<span class="icon-refresh"></span>
</div>
</div>
+ <div class="instantiationStatusFilter" *ngIf=isInstantiationStatusFilterFlagOn()>
+ <input
+ [attr.data-tests-id]="'instantiation-status-filter'"
+ class="form-control input-text"
+ [placeholder]="'filter'"
+ [(ngModel)]="filterText">
+ </div>
</div>
</div>
</div>
@@ -41,51 +48,51 @@
</tr>
</thead>
<tbody >
- <tr *ngFor="let data of serviceInfoData; trackBy: trackByFn; let i = index" [ngClass]="{'odd' : data.serviceIndex%2 == 1}" [id]="data.jobId">
- <td class="smallTd" id="userId"><custom-ellipsis [id]="data.userId" [value]="data.userId"></custom-ellipsis></td>
- <td class="smallTd" id="action"><custom-ellipsis [id]="data.action" [value]="data.action | capitalizeAndFormat"></custom-ellipsis></td>
- <td class="normal" id="serviceModelName"><custom-ellipsis [id]="data.serviceModelName" [value]="data.serviceModelName"></custom-ellipsis></td>
- <td class="normal" id="serviceInstanceName"><custom-ellipsis [id]="data.serviceInstanceName" [value]="data.serviceInstanceName"></custom-ellipsis></td>
- <td class="smallTd" id="serviceModelVersion"><custom-ellipsis [id]="data.serviceModelVersion" [value]="data.serviceModelVersion"></custom-ellipsis></td>
- <td class="normal" id="subscriberName"><custom-ellipsis [id]="data.subscriberName" [value]="data.subscriberName"></custom-ellipsis></td>
- <td class="mediumTd" id="serviceType"><custom-ellipsis [id]="data.serviceType" [value]="data.serviceType"></custom-ellipsis></td>
- <td class="normal" id="regionId"><custom-ellipsis [id]="data.regionId" [value]="data.regionId"></custom-ellipsis></td>
- <td class="mediumTd" id="tenantName"><custom-ellipsis [id]="data.tenantName" [value]="data.tenantName"></custom-ellipsis></td>
- <td class="mediumTd" id="aicZoneName"><custom-ellipsis [id]="data.aicZoneName" [value]="data.aicZoneName"></custom-ellipsis></td>
- <td class="mediumTd" id="project"><custom-ellipsis [id]="data.project" [value]="data.project"></custom-ellipsis></td>
- <td class="mediumTd" id="owningEntityName"><custom-ellipsis [id]="data.owningEntityName" [value]="data.owningEntityName"></custom-ellipsis></td>
- <td class="smallTd" id="pause"><custom-ellipsis [id]="data.pause" [value]="data.pause"></custom-ellipsis></td>
- <td class="mediumTd" id="created"><custom-ellipsis [id]="data.created" [value]="data.created | date:'MMM. dd, yyyy HH:mm'"></custom-ellipsis></td>
- <td class="last" id="jobStatus" [ngClass]="data.jobStatus">
- <custom-popover [value]="data.serviceStatus.tooltip" [popoverType]="data?.serviceStatus?.color" style="float: left;">
- <svg-icon
- id="jobStatusIcon-{{i}}"
- (click)="auditInfo(data)"
- [mode]="data.serviceStatus.color"
- [size]="'large'"
- [name]="data.serviceStatus.iconClassName">
- </svg-icon>
+ <tr *ngFor="let data of serviceInfoData | searchFilter: filterText ; trackBy: trackByFn; let i = index" [ngClass]="{'odd' : data.serviceIndex%2 == 1}" [id]="data.jobId">
+ <td class="smallTd" id="userId"><custom-ellipsis [id]="data.userId" [value]="data.userId"></custom-ellipsis></td>
+ <td class="smallTd" id="action"><custom-ellipsis [id]="data.action" [value]="data.action | capitalizeAndFormat"></custom-ellipsis></td>
+ <td class="normal" id="serviceModelName"><custom-ellipsis [id]="data.serviceModelName" [value]="data.serviceModelName"></custom-ellipsis></td>
+ <td class="normal" id="serviceInstanceName"><custom-ellipsis [id]="data.serviceInstanceName" [value]="data.serviceInstanceName"></custom-ellipsis></td>
+ <td class="smallTd" id="serviceModelVersion"><custom-ellipsis [id]="data.serviceModelVersion" [value]="data.serviceModelVersion"></custom-ellipsis></td>
+ <td class="normal" id="subscriberName"><custom-ellipsis [id]="data.subscriberName" [value]="data.subscriberName"></custom-ellipsis></td>
+ <td class="mediumTd" id="serviceType"><custom-ellipsis [id]="data.serviceType" [value]="data.serviceType"></custom-ellipsis></td>
+ <td class="normal" id="regionId"><custom-ellipsis [id]="data.regionId" [value]="data.regionId"></custom-ellipsis></td>
+ <td class="mediumTd" id="tenantName"><custom-ellipsis [id]="data.tenantName" [value]="data.tenantName"></custom-ellipsis></td>
+ <td class="mediumTd" id="aicZoneName"><custom-ellipsis [id]="data.aicZoneName" [value]="data.aicZoneName"></custom-ellipsis></td>
+ <td class="mediumTd" id="project"><custom-ellipsis [id]="data.project" [value]="data.project"></custom-ellipsis></td>
+ <td class="mediumTd" id="owningEntityName"><custom-ellipsis [id]="data.owningEntityName" [value]="data.owningEntityName"></custom-ellipsis></td>
+ <td class="smallTd" id="pause"><custom-ellipsis [id]="data.pause" [value]="data.pause"></custom-ellipsis></td>
+ <td class="mediumTd" id="created"><custom-ellipsis [id]="data.created" [value]="data.created | date:'MMM. dd, yyyy HH:mm'"></custom-ellipsis></td>
+ <td class="last" id="jobStatus" [ngClass]="data.jobStatus">
+ <custom-popover [value]="data.serviceStatus.tooltip" [popoverType]="data?.serviceStatus?.color" style="float: left;">
+ <svg-icon
+ id="jobStatusIcon-{{i}}"
+ (click)="auditInfo(data)"
+ [mode]="data.serviceStatus.color"
+ [size]="'large'"
+ [name]="data.serviceStatus.iconClassName">
+ </svg-icon>
- </custom-popover>
- <div class="menu-div" (click)="onContextMenu($event, data)">
- <span class="icon-menu"></span>
- <context-menu>
- <ng-template *ngFor="let action of contextMenuActions" contextMenuItem let-item
- [visible]="action.visible"
- [enabled]="action.enabled"
- (execute)="action.click($event.item)">
- <div [attr.data-tests-id]="action.dataTestId"
- [tooltip]="action?.tooltip"
- [tooltipDisabled]="!action.tooltip">
+ </custom-popover>
+ <div class="menu-div" (click)="onContextMenu($event, data)" [attr.data-tests-id]="'menu-'+data.jobId">
+ <span class="icon-menu"></span>
+ <context-menu>
+ <ng-template *ngFor="let action of contextMenuActions" contextMenuItem let-item
+ [visible]="action.visible"
+ [enabled]="action.enabled"
+ (execute)="action.click($event.item)">
+ <div [attr.data-tests-id]="action.dataTestId"
+ [tooltip]="action?.tooltip"
+ [tooltipDisabled]="!action.tooltip">
<span class="context-menu-icon">
<i class="fa {{action.className}}" aria-hidden="true"></i>
</span>
- {{action.name}}
- </div>
- </ng-template>
- </context-menu>
- </div>
- </td>
+ {{action.name}}
+ </div>
+ </ng-template>
+ </context-menu>
+ </div>
+ </td>
</tr>
</tbody>
</table>
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.scss b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.scss
index 65c2400a3..352a7db10 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.scss
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.scss
@@ -275,3 +275,9 @@ div.dataTables_wrapper {
margin-top: 0px;
height: 0;
}
+
+.instantiationStatusFilter {
+ position: absolute;
+ right: 20px;
+ width: 22%;
+}
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts
index 27d3f419b..eedd46dd3 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts
@@ -1,49 +1,29 @@
import {getTestBed, TestBed} from '@angular/core/testing';
-import {
- COMPLETED_WITH_ERRORS,
- INPROGRESS,
- InstantiationStatusComponentService,
- PAUSE,
- PENDING,
- ServiceStatus,
- STOPPED,
- SUCCESS_CIRCLE,
- UNKNOWN,
- X_O
-} from './instantiationStatus.component.service';
+import {COMPLETED_WITH_ERRORS, INPROGRESS, InstantiationStatusComponentService, PAUSE, PENDING, ServiceStatus, STOPPED, SUCCESS_CIRCLE, UNKNOWN, X_O} from './instantiationStatus.component.service';
import {ServiceInfoModel} from '../shared/server/serviceInfo/serviceInfo.model';
import {AaiService} from "../shared/services/aaiService/aai.service";
import {MsoService} from "../shared/services/msoService/mso.service";
import {NgRedux} from "@angular-redux/store";
import {HttpClientTestingModule} from "@angular/common/http/testing";
-import {FeatureFlagsService} from "../shared/services/featureFlag/feature-flags.service";
+import {FeatureFlagsService, Features} from "../shared/services/featureFlag/feature-flags.service";
import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes";
import {RouterTestingModule} from "@angular/router/testing";
import {of} from "rxjs";
import {UrlTree} from "@angular/router";
+import each from "jest-each";
+import {ServiceAction} from "../shared/models/serviceInstanceActions";
+import {instance, mock, when} from "ts-mockito";
class MockAppStore<T> {
-
- getState() {
- return {
- global: {
- flags: {
- 'FLAG_1902_NEW_VIEW_EDIT': true,
-
- }
- }
- }
- }
-
- dispatch() {
-
- }
+ dispatch() {}
}
+
describe('Instantiation Status Service', () => {
let injector;
let aaiService: AaiService;
let msoService: MsoService;
let service: InstantiationStatusComponentService;
+ let mockFeatureFlagsService: FeatureFlagsService = mock(FeatureFlagsService);
beforeAll(done => (async () => {
@@ -57,7 +37,9 @@ describe('Instantiation Status Service', () => {
AaiService,
MsoService,
FeatureFlagsService,
- {provide: NgRedux, useClass: MockAppStore}]
+ {provide: NgRedux, useClass: MockAppStore},
+ {provide: FeatureFlagsService, useValue: instance(mockFeatureFlagsService)}
+ ]
});
await TestBed.compileComponents();
@@ -101,33 +83,48 @@ describe('Instantiation Status Service', () => {
});
});
- test('click on "Open" button should open new view edit' , ()=>{
- const item = {
- serviceModelId : 'serviceModelId',
- serviceInstanceId : 'serviceInstanceId',
- serviceType : 'serviceType',
- subscriberId : 'subscriberId'
- };
- let params:UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.VIEW);
- expect(params.toString().startsWith('/servicePlanning/VIEW')).toBeTruthy();
- expect(params.queryParams).toEqual(
- {
- serviceModelId: item.serviceModelId,
- serviceInstanceId: item.serviceInstanceId,
- serviceType : item.serviceType,
- subscriberId : item.subscriberId
- });
- });
+ describe('navigations tests:', () => {
- test('build the View Edit url' , ()=>{
const item = {
- serviceModelId : '28aeb8f6-5620-4148-8bfb-a5fb406f0309',
+ serviceModelId: '28aeb8f6-5620-4148-8bfb-a5fb406f0309',
+ serviceInstanceId: 'myInstanceId',
+ serviceType: 'myService',
+ subscriberId: 'mySubscriber',
+ jobId: 'aJobId'
};
- let serviceModelUrl: string = '/servicePlanning/EDIT?serviceModelId=28aeb8f6-5620-4148-8bfb-a5fb406f0309';
- let suffix:string = '../../serviceModels.htm#';
- let tree:UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.EDIT);
- let result = service.getViewEditUrl(tree);
- expect (suffix + serviceModelUrl).toEqual(result);
+
+ test('click on "Open" button should open new view edit', () => {
+ let params: UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.VIEW);
+ expect(params.toString().startsWith('/servicePlanning/VIEW')).toBeTruthy();
+ expect(params.queryParams).toEqual(
+ {
+ serviceModelId: item.serviceModelId,
+ serviceInstanceId: item.serviceInstanceId,
+ serviceType: item.serviceType,
+ subscriberId: item.subscriberId,
+ jobId: item.jobId
+ });
+ });
+
+ test('build the View Edit url', () => {
+
+ let serviceModelUrl: string = '/servicePlanning/EDIT?serviceModelId=28aeb8f6-5620-4148-8bfb-a5fb406f0309' +
+ '&serviceInstanceId=myInstanceId&serviceType=myService&subscriberId=mySubscriber&jobId=aJobId';
+ let prefix: string = '../../serviceModels.htm#';
+ let tree: UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.EDIT);
+ let result = service.getViewEditUrl(tree);
+ expect(result).toEqual(prefix + serviceModelUrl);
+ });
+
+ test('recreate url shall contains mode RECREATE and only jobId and serviceModelId', () =>{
+ let params: UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.RECREATE);
+ expect(params.toString().startsWith('/servicePlanning/RECREATE')).toBeTruthy();
+ expect(params.queryParams).toEqual(
+ {
+ serviceModelId: item.serviceModelId,
+ jobId: item.jobId
+ });
+ });
});
for (let [status, tooltip] of Object.entries({
@@ -154,6 +151,27 @@ describe('Instantiation Status Service', () => {
expect(statusResult.iconClassName).toEqual(UNKNOWN);
});
+
+ each([
+ [true, ServiceAction.INSTANTIATE],
+ [false, ServiceAction.UPDATE],
+ [false, ServiceAction.DELETE],
+ ]).
+ test('isRecreateEnabled: should be %s if action is %s', (expected:boolean, action:ServiceAction) => {
+ let serviceInfoModel = new ServiceInfoModel();
+ serviceInfoModel.action = action;
+ expect(service.isRecreateEnabled(serviceInfoModel)).toBe(expected);
+ });
+
+ each([
+ [true, true],
+ [false, false],
+ ]).
+ test('isRecreateVisible: should be %s if flag is %s', (expected:boolean, flag:boolean) => {
+ when(mockFeatureFlagsService.getFlagState(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE)).thenReturn(flag);
+ expect(service.isRecreateVisible()).toEqual(expected);
+ });
+
test('getStatusTooltip should return correct icon per job status', () => {
let result : ServiceStatus = service.getStatus('pending');
expect(result.iconClassName).toEqual(PENDING);
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts
index ffc2e681a..4bfedd913 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts
@@ -12,6 +12,7 @@ import {updateDrawingBoardStatus} from "../shared/storeUtil/utils/global/global.
import {Router, UrlTree} from "@angular/router";
import {of} from "rxjs";
import {MsoService} from "../shared/services/msoService/mso.service";
+import {ServiceAction} from "../shared/models/serviceInstanceActions";
export let PENDING : string = "pending";
export let INPROGRESS : string = "in_progress";
@@ -28,7 +29,8 @@ export class InstantiationStatusComponentService {
constructor( private _aaiService: AaiService,
private _msoService: MsoService,
private _router : Router,
- private _store: NgRedux<AppState>) {
+ private _store: NgRedux<AppState>,
+ private _featureFlagsService:FeatureFlagsService) {
}
generateServiceInfoDataMapping(arr: ServiceInfoModel[]) : { [serviceInstanceId: string]: ServiceInfoModel[]}{
@@ -69,7 +71,7 @@ export class InstantiationStatusComponentService {
}
open(item: ServiceInfoModel): void {
- if (FeatureFlagsService.getFlagState(Features.FLAG_1902_VNF_GROUPING, this._store)) {
+ if (this._featureFlagsService.getFlagState(Features.FLAG_1902_VNF_GROUPING)) {
this._aaiService.getServiceModelById(item['serviceModelId']).subscribe((result)=>{
const serviceModel = new ServiceModel(result);
@@ -91,7 +93,7 @@ export class InstantiationStatusComponentService {
}
navigateToNewViewOnlyOrOldEditView(item: ServiceInfoModel) {
- if (FeatureFlagsService.getFlagState(Features.FLAG_1902_NEW_VIEW_EDIT, this._store)) {
+ if (this._featureFlagsService.getFlagState(Features.FLAG_1902_NEW_VIEW_EDIT)) {
this.navigateToNewViewEdit(item, DrawingBoardModes.VIEW);
}
else {
@@ -122,19 +124,31 @@ export class InstantiationStatusComponentService {
['/servicePlanning/' + mode],
{
queryParams:
- {
- serviceModelId: item.serviceModelId,
- serviceInstanceId: item.serviceInstanceId,
- serviceType : item.serviceType,
- subscriberId : item.subscriberId,
- jobId: item.jobId
- }
+ mode==DrawingBoardModes.RECREATE ?
+ this.getRecreateQueryParams(item) :
+ this.getDefaultViewEditQueryParams(item)
});
}
+ private getDefaultViewEditQueryParams(item: ServiceInfoModel) {
+ return {
+ serviceModelId: item.serviceModelId,
+ serviceInstanceId: item.serviceInstanceId,
+ serviceType: item.serviceType,
+ subscriberId: item.subscriberId,
+ jobId: item.jobId
+ };
+ }
+
+ private getRecreateQueryParams(item: ServiceInfoModel) {
+ return {
+ serviceModelId: item.serviceModelId,
+ jobId: item.jobId
+ };
+ }
+
getViewEditUrl(viewEditUrlTree:UrlTree): string {
return '../../serviceModels.htm#' + viewEditUrlTree.toString();
-
}
getStatus(status : string) : ServiceStatus {
@@ -162,6 +176,18 @@ export class InstantiationStatusComponentService {
retry(item: ServiceInfoModel): void {
this.navigateToNewViewEdit(item, DrawingBoardModes.RETRY_EDIT);
}
+
+ recreate(item: ServiceInfoModel): void {
+ this.navigateToNewViewEdit(item, DrawingBoardModes.RECREATE);
+ }
+
+ isRecreateEnabled(item: ServiceInfoModel): boolean {
+ return item.action === ServiceAction.INSTANTIATE;
+ }
+
+ isRecreateVisible(): boolean {
+ return this._featureFlagsService.getFlagState(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE);
+ }
}
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts
index 53dfcc1f2..e6ccdda8e 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts
@@ -17,7 +17,10 @@ import {FeatureFlagsService} from "../shared/services/featureFlag/feature-flags.
import {JobStatus, ServiceAction} from "../shared/models/serviceInstanceActions";
import each from 'jest-each';
import {ServiceInfoModel} from "../shared/server/serviceInfo/serviceInfo.model";
-import { TooltipModule } from 'ngx-tooltip';
+import {TooltipModule} from 'ngx-tooltip';
+import {SearchFilterPipe} from "../shared/pipes/searchFilter/search-filter.pipe";
+import {ActivatedRoute} from "@angular/router";
+import {FormsModule} from "@angular/forms";
class MockAppStore<T> {
@@ -36,10 +39,21 @@ class MockAppStore<T> {
}
}
+class ActivatedRouteMock<T>{
+ queryParams() {
+ return {}
+ };
+
+ snapshot = {
+ queryParams : {}
+ }
+}
+
describe('Instantiation Status Component', () => {
let component: InstantiationStatusComponent;
let fixture: ComponentFixture<InstantiationStatusComponent>;
-let item = new ServiceInfoModel();
+ let item = new ServiceInfoModel();
+
beforeAll(done => (async () => {
TestBed.configureTestingModule({
@@ -48,7 +62,8 @@ let item = new ServiceInfoModel();
ContextMenuModule,
ScrollToModule.forRoot(),
RouterTestingModule,
- TooltipModule
+ TooltipModule,
+ FormsModule,
],
providers: [
ServiceInfoService,
@@ -59,9 +74,10 @@ let item = new ServiceInfoModel();
FeatureFlagsService,
ConfigurationService,
LogService,
+ {provide: ActivatedRoute, useClass: ActivatedRouteMock},
{provide: NgRedux, useClass: MockAppStore}
],
- declarations: [InstantiationStatusComponent, CapitalizeAndFormatPipe],
+ declarations: [InstantiationStatusComponent, CapitalizeAndFormatPipe, SearchFilterPipe],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
});
await TestBed.compileComponents();
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts
index f3f651960..58227c9eb 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts
@@ -1,4 +1,4 @@
-import {Component, ViewChild} from '@angular/core';
+import {Component, OnInit, ViewChild} from '@angular/core';
import {ServiceInfoService} from '../shared/server/serviceInfo/serviceInfo.service';
import {ServiceInfoModel} from '../shared/server/serviceInfo/serviceInfo.model';
import {InstantiationStatusComponentService} from './instantiationStatus.component.service';
@@ -11,7 +11,8 @@ import {LogService} from '../shared/utils/log/log.service';
import {AppState} from "../shared/store/reducers";
import {NgRedux} from '@angular-redux/store';
import {JobStatus, ServiceAction} from "../shared/models/serviceInstanceActions";
-import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes";
+import {ActivatedRoute} from "@angular/router";
+import {FeatureFlagsService, Features} from "../shared/services/featureFlag/feature-flags.service";
export interface MenuAction{
name: string;
@@ -28,7 +29,7 @@ export interface MenuAction{
templateUrl : './instantiationStatus.component.html',
styleUrls : ['./instantiationStatus.component.scss']
})
-export class InstantiationStatusComponent {
+export class InstantiationStatusComponent implements OnInit {
TIMER_TIME_IN_SECONDS : number = 0;
timer = null;
@@ -58,6 +59,14 @@ export class InstantiationStatusComponent {
visible: () => true,
},
{
+ name: "Recreate",
+ dataTestId: "context-menu-recreate",
+ className: "fa-clone",
+ click: (item: ServiceInfoModel) => this.instantiationStatusComponentService.recreate(item),
+ enabled: (item: ServiceInfoModel) => this.instantiationStatusComponentService.isRecreateEnabled(item),
+ visible: () => this.instantiationStatusComponentService.isRecreateVisible(),
+ },
+ {
name: "Audit info",
dataTestId: "context-menu-audit-info",
className: "fa-info-circle",
@@ -85,12 +94,14 @@ export class InstantiationStatusComponent {
];
flags: any;
+ filterText: string;
constructor(private _serviceInfoService: ServiceInfoService,
private _instantiationStatusComponentService : InstantiationStatusComponentService,
private _contextMenuService: ContextMenuService,
private _configurationService : ConfigurationService,
private _scrollToService: ScrollToService,
private _logService : LogService,
+ private route: ActivatedRoute,
private _store: NgRedux<AppState>) {
this.instantiationStatusComponentService = _instantiationStatusComponentService;
this.configurationService = this._configurationService;
@@ -101,6 +112,11 @@ export class InstantiationStatusComponent {
});
}
+ ngOnInit() {
+ let filterTextParam = this.route.snapshot.queryParams["filterText"];
+ this.filterText = filterTextParam ? filterTextParam : "" ;
+ }
+
activateInterval() {
if (this.TIMER_TIME_IN_SECONDS > 0) {
this.timer = setInterval(() => {
@@ -115,7 +131,7 @@ export class InstantiationStatusComponent {
refreshData(): void {
this.dataIsReady = false;
- this._serviceInfoService.getServicesJobInfo(true, this.lastUpdatedDate === null)
+ this._serviceInfoService.getServicesJobInfo(this.lastUpdatedDate === null)
.subscribe((res: ServiceInfoModel[]) => {
this._instantiationStatusComponentService.convertObjectToArray(res).subscribe((res) => {
this._logService.info('refresh instantiation status table', res);
@@ -144,7 +160,7 @@ export class InstantiationStatusComponent {
this.refreshData();
});
}
-
+
retryItem(item: ServiceInfoModel) : void {
if (item.isRetryEnabled) {
this._instantiationStatusComponentService.retry(item);
@@ -230,4 +246,8 @@ export class InstantiationStatusComponent {
}, 0)
}
}
+
+ isInstantiationStatusFilterFlagOn() {
+ return FeatureFlagsService.getFlagState(Features.FLAG_2004_INSTANTIATION_STATUS_FILTER, this._store);
+ }
}
diff --git a/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts b/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts
index 07f4d481b..a7b8ac744 100644
--- a/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts
+++ b/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts
@@ -3,18 +3,20 @@ import {HighlightPipe} from "../../pipes/highlight/highlight-filter.pipe";
import * as _ from 'lodash';
@Component({
- selector : 'custom-ellipsis',
+ selector: 'custom-ellipsis',
template: `
<span
- sdc-tooltip
- class="ellipsis"
- id="{{id}}"
- [innerHtml]="displayValue | safe : 'html'"
- [ngClass]="{'breakWord' : breakWord == true}"
- [tooltip-text]="value">
+ sdc-tooltip
+ class="ellipsis"
+ [attr.data-tests-id]="dataTestId"
+ id="{{id}}"
+ [innerHtml]="displayValue | safe : 'html'"
+ [ngStyle]="{'white-space' : showDots ? 'nowrap' : 'initial'}"
+ [ngClass]="{'breakWord' : breakWord == true}"
+ [tooltip-text]="value">
</span>`,
- styles : [
- `
+ styles: [
+ `
.ellipsis {
white-space: nowrap;
overflow: hidden;
@@ -23,30 +25,33 @@ import * as _ from 'lodash';
width: 99%;
text-align: left;
}
-
+
.breakWord {
word-wrap: break-word;
white-space: normal;
}
`
],
- providers : [HighlightPipe]
+ providers: [HighlightPipe]
})
-export class EllipsisComponent implements OnChanges{
- @Input() value : string;
- @Input() id : string;
- @Input() hightlight : string;
- @Input() breakWord : boolean = false;
+export class EllipsisComponent implements OnChanges {
+ @Input() value: string;
+ @Input() id: string;
+ @Input() hightlight: string;
+ @Input() breakWord: boolean = false;
+ @Input() dataTestId: string;
+ @Input() showDots: boolean = false;
+
+ displayValue: string;
- displayValue : string;
- constructor(private _highlightPipe : HighlightPipe){
+ constructor(private _highlightPipe: HighlightPipe) {
this.displayValue = this.value;
}
ngOnChanges(changes: SimpleChanges): void {
this.displayValue = this.value;
- if(!_.isNil(this.hightlight)){
- this.displayValue = this._highlightPipe.transform(this.value ,this.hightlight ? this.hightlight : '');
+ if (!_.isNil(this.hightlight)) {
+ this.displayValue = this._highlightPipe.transform(this.value, this.hightlight ? this.hightlight : '');
}
}
}
diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html
index f7c4894b2..f205259e4 100644
--- a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html
+++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html
@@ -1,16 +1,26 @@
-<div>
- <div class="details-item" *ngIf="data != null && form != null">
- <label [ngClass]="{'required': data.isRequired()}"
- for="{{data?.dataTestId}}">{{data?.displayName}}:</label>
- <angular2-multiselect id="{{data?.dataTestId}}"
- [attr.data-tests-id]="data?.dataTestId"
- [formControl]="form.controls[data.controlName]"
- [(ngModel)]="data.selectedItems"
- [data]="data?.options$"
- [settings]="data?.settings"
- title="{{data.tooltip}}"
- [ngClass]="{'error-style' : form?.controls[data?.controlName]?.touched && form?.controls[data?.controlName]?.errors}">
- </angular2-multiselect>
- </div>
-</div>
+<div class="details-item" *ngIf="data != null && form != null">
+ <label [ngClass]="{'required': data.isRequired()}"
+ for="{{data?.dataTestId}}-select">{{data?.displayName}}:</label>
+
+ <angular2-multiselect
+ [attr.data-tests-id]="data?.dataTestId"
+ [data]="options"
+ [(ngModel)]="selectedItems"
+ [settings]="dropdownSettings"
+ (onSelect)="onItemSelect($event)"
+ (onDeSelect)="OnItemDeSelect($event)"
+ (onSelectAll)="onSelectAll($event)"
+ (onDeSelectAll)="onDeSelectAll($event)">>
+ <c-item>
+ <ng-template let-item="item">
+ <label
+ [attr.data-tests-id]="data.dataTestId + '-' + item?.itemName"
+ style="color: #333;min-width: 150px;">{{item?.itemName}}</label>
+ </ng-template>
+ </c-item>
+ </angular2-multiselect>
+
+ <form-control-error *ngIf="data?.hasEmptyOptions && data?.isRequired()"
+ [message]="'No results for this request. Please change criteria.'"></form-control-error>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts
deleted file mode 100644
index 81c8d4679..000000000
--- a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import {ComponentFixture, TestBed} from '@angular/core/testing';
-import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'
-import {CommonModule} from "@angular/common";
-import {FormBuilder, FormControl, ReactiveFormsModule, Validators} from "@angular/forms";
-import {
- ValidatorModel,
- ValidatorOptions
-} from "../../../../models/formControlModels/formControl.model";
-import {FormControlMessageErrorComponent} from "../../errorMessage/formControlMessageError.component";
-import {BrowserModule} from "@angular/platform-browser";
-import {MultiselectFormControlComponent} from "./multiselect.formControl.component";
-import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model";
-import { of } from "rxjs";
-describe('Dropdown Form Control Component', () => {
- let component: MultiselectFormControlComponent;
- let fixture: ComponentFixture<MultiselectFormControlComponent>;
- let fb: FormBuilder;
-
- beforeAll(done => (async () => {
- TestBed.configureTestingModule({
- imports: [CommonModule, BrowserModule, ReactiveFormsModule],
- providers: [FormBuilder],
- declarations: [MultiselectFormControlComponent, FormControlMessageErrorComponent],
- schemas: [CUSTOM_ELEMENTS_SCHEMA]
- });
- await TestBed.compileComponents();
-
- fixture = TestBed.createComponent(MultiselectFormControlComponent);
- component = fixture.componentInstance;
- fb = TestBed.get(FormBuilder);
-
- })().then(done).catch(done.fail));
-
- test('component should initialize basic parameters', () => {
- component.data = new MultiselectFormControl({
- displayName: "display Name",
- validations: [new ValidatorModel(ValidatorOptions.required, 'is required')],
- dataTestId: "data-test-id",
- placeHolder: "place holder",
- controlName: 'testDropdown',
- options: of([
- 'option1',
- 'option2',
- 'option3',
- 'onBlur'
- ])
- });
-
- component.data.hasErrors = function () {
- return this.formGroup.controls[this.controlName].touched && this.formGroup.controls[this.controlName].errors ? ['error-style'] : [];
- };
-
- component.data.onBlur = function () {
- component.form.controls['testDropdown'].setValue('onBlur');
- };
-
- component.form = fb.group({
- 'testDropdown': new FormControl({
- value: component.data.value,
- disabled: false
- }, Validators.compose(component.data.validations.map(item => item.validator)))
- });
-
- component.form.controls['testDropdown'].setValue('');
- expect(component.form.controls['testDropdown'].errors.required).toBeTruthy();
- component.form.controls['testDropdown'].setValue('option2');
- expect(component.form.controls['testDropdown'].errors).toBeFalsy();
- component.data.onBlur();
- expect(component.form.controls['testDropdown'].value).toEqual('onBlur');
- expect(component.form.controls['testDropdown'].errors).toBeFalsy();
- }
- )
-});
-
diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts
index 4b98c7e26..26a55e9d2 100644
--- a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts
+++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts
@@ -1,6 +1,8 @@
import {Component, Input, OnChanges, SimpleChanges} from "@angular/core";
import {FormGroup} from "@angular/forms";
import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model";
+import {MultiselectFormControlService} from "./multiselect.formControl.service";
+import {MultiSelectItem} from "./multiselect.model";
@Component({
selector: 'multiselect-form-control',
@@ -8,13 +10,54 @@ import {MultiselectFormControl} from "../../../../models/formControlModels/multi
})
export class MultiselectFormControlComponent implements OnChanges{
@Input() data: MultiselectFormControl = null;
+ @Input() multiselectOptions: [] = null;
+ @Input() selectedItems = [];
@Input() form: FormGroup = null;
- ngOnChanges(changes: SimpleChanges): void {
+
+ multiselectFormControlService : MultiselectFormControlService;
+ constructor(private _multiselectFormControlService : MultiselectFormControlService){
+ this.multiselectFormControlService = _multiselectFormControlService;
+ }
+
+ dropdownSettings = {
+ singleSelection : false,
+ limitSelection : 1000
+ };
+
+ options : MultiSelectItem[];
+
+
+
+ async ngOnChanges(changes: SimpleChanges) {
+ if(this.data.options$){
+ this._multiselectFormControlService.convertOriginalItems(this.data).then((options)=>{
+ this.options = options;
+ this._multiselectFormControlService.convertSelectedItems(this.data).then((res)=> {
+ this.selectedItems = res;
+ this.form.controls[this.data.controlName].setValue(this.selectedItems);
+ })
+ });
+ }
if (changes["data"] !== undefined && changes["data"].currentValue !== changes["data"].previousValue && changes["data"].firstChange) {
- if(this.data.onInit){
+ if (this.data.onInit) {
+ this.dropdownSettings.limitSelection = this.data.limitSelection;
this.data.onInit(this.data, this.form);
}
}
}
+
+ onItemSelect(item:any){
+ this.data.onChange(this.selectedItems ,this.form);
+ }
+ OnItemDeSelect(item:any){
+ this.data.onChange(this.selectedItems ,this.form);
+ }
+ onSelectAll(items: any){
+ this.data.onChange(this.selectedItems ,this.form);
+ }
+ onDeSelectAll(items: any){
+ this.data.onChange(this.selectedItems ,this.form);
+ }
}
+
diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.spec.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.spec.ts
new file mode 100644
index 000000000..3c3c344a3
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.spec.ts
@@ -0,0 +1,159 @@
+import {async, getTestBed, TestBed} from '@angular/core/testing';
+import {MultiselectFormControlService} from "./multiselect.formControl.service";
+import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model";
+import {MultiSelectItem} from "./multiselect.model";
+
+describe('Multi Select Form Control Service', () => {
+
+ let injector;
+ let service: MultiselectFormControlService;
+
+ beforeAll(done => (async () => {
+ TestBed.configureTestingModule({
+ imports: [],
+ providers: [MultiselectFormControlService]
+ });
+ await TestBed.compileComponents();
+ injector = getTestBed();
+ service = injector.get(MultiselectFormControlService);
+ })().then(done).catch(done.fail));
+
+
+ const options = [
+ {
+ id: 'A',
+ name: 'a'
+ },
+ {
+ id: 'B',
+ name: 'b',
+ keepMe: -42
+ },
+ {
+ id: 'C',
+ name: 'c'
+ }
+ ],
+ selectedFieldName = 'name',
+ ngValue = 'id';
+
+
+ test('convertOriginalItems should convert options array to <MultiSelectItem> list', async(() => {
+ let control: MultiselectFormControl = <any>{
+ ngValue,
+ selectedFieldName,
+ options$: options
+ };
+
+ service.convertOriginalItems(control).then((result: MultiSelectItem[]) => {
+ expect(result).toEqual([
+ {"id": 1, "itemId": 'A', "itemName": 'a'},
+ {"id": 2, "itemId": 'B', "itemName": 'b'},
+ {"id": 3, "itemId": 'C', "itemName": 'c'}
+ ]);
+ });
+ }));
+
+ test('convertOriginalItems should return empty list when options list is empty', async(() => {
+ let control: MultiselectFormControl = <any>{
+ ngValue,
+ selectedFieldName,
+ options$: []
+ };
+
+ service.convertOriginalItems(control).then((result) => {
+ expect(result).toEqual([]);
+ });
+ }));
+
+ test('convertOptionsToHashMap - should convert any object to hash map with ngValue', async(() => {
+
+ let control: MultiselectFormControl = <any>{
+ ngValue,
+ selectedFieldName,
+ options$: options
+ };
+
+ let map = service.convertOptionsToHashMap(control);
+
+ expect(Object.keys(map)).toHaveLength(3);
+ expect(map).toEqual({
+ 'A': {
+ id: 'A',
+ name: 'a',
+ index: 1
+ },
+ 'B': {
+ id: 'B',
+ name: 'b',
+ keepMe: -42,
+ index: 2
+ },
+ 'C': {
+ id: 'C',
+ name: 'c',
+ index: 3
+ }
+
+ })
+ }));
+
+ test('convertOptionsToHashMap - should convert any object to hash map with ngValue: empty options', async(() => {
+ let control: MultiselectFormControl = <any>{
+ ngValue,
+ selectedFieldName,
+ options$: []
+ };
+
+ let map = service.convertOptionsToHashMap(control);
+
+ expect(Object.keys(map)).toHaveLength(0)
+ }));
+
+ test('convertSelectedItems - should convert select item to multi select list', async(() => {
+ let control: MultiselectFormControl = <any>{
+ ngValue,
+ selectedFieldName,
+ options$: options,
+ value: ['A', 'C']
+ };
+
+ service.convertSelectedItems(control).then((selectedOptions) => {
+ expect(selectedOptions).toHaveLength(2);
+ expect(selectedOptions[0].itemName).toEqual('a');
+ expect(selectedOptions[1].itemName).toEqual('c');
+ })
+ }));
+
+ test('convertSelectedItems - should convert select item to multi select list with special convert function', async(() => {
+ let control: MultiselectFormControl = <any>{
+ ngValue,
+ selectedFieldName,
+ options$: options,
+ value: 'A,C',
+ convertOriginalDataToArray: (value) => {
+ return value.split(',');
+ }
+ };
+
+ service.convertSelectedItems(control).then((selectedOptions) => {
+ expect(selectedOptions).toHaveLength(2);
+ expect(selectedOptions[0].itemName).toEqual('a');
+ expect(selectedOptions[1].itemName).toEqual('c');
+ })
+ }));
+
+
+ test('convertSelectedItems - should return empty list iof value is empty list', async(() => {
+ let control: MultiselectFormControl = <any>{
+ ngValue,
+ selectedFieldName,
+ options$: options,
+ value: []
+ };
+
+ service.convertSelectedItems(control).then((selectedOptions) => {
+ expect(selectedOptions).toHaveLength(0);
+ })
+ }));
+});
diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts
new file mode 100644
index 000000000..0b50f4d28
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts
@@ -0,0 +1,50 @@
+import {Injectable} from "@angular/core";
+import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model";
+import {MultiSelectItem} from "./multiselect.model";
+import * as _ from "lodash";
+
+
+@Injectable()
+export class MultiselectFormControlService {
+
+ convertOriginalItems = (control : MultiselectFormControl) : Promise<MultiSelectItem[]> => {
+ return new Promise<MultiSelectItem[]>((resolve) =>{
+ let result: MultiSelectItem[] = [];
+ if(control.options$) {
+ let index: number = 1;
+ control.options$.map((originalItems: any) => {
+ result.push(new MultiSelectItem(index, originalItems[control.ngValue], originalItems[control.selectedFieldName]));
+ index++;
+ });
+ }
+ resolve(result);
+ })
+ };
+
+
+ convertOptionsToHashMap = (config : MultiselectFormControl) => {
+ let index = 1;
+ return _.reduce(config.options$ , (obj, param: any ) => {
+ param.index = index;
+ index++;
+ obj[param[config.ngValue]] = param;
+ return obj;
+ }, {});
+ };
+
+ convertSelectedItems(control : MultiselectFormControl) : Promise<MultiSelectItem[]>{
+ return new Promise<MultiSelectItem[]>((resolve) =>{
+ let result: MultiSelectItem[] = [];
+ const hashMap = this.convertOptionsToHashMap(control);
+
+ if(control.options$ && control.value) {
+ const convertArray = control.convertOriginalDataToArray ? control.convertOriginalDataToArray(control.value) : control.value;
+ convertArray.map((itemId) => {
+ const uniqueIdentifier = itemId.trim();
+ result.push(new MultiSelectItem(hashMap[uniqueIdentifier].index, hashMap[uniqueIdentifier][control.ngValue], hashMap[uniqueIdentifier][control.selectedFieldName]));
+ });
+ }
+ resolve(result);
+ });
+ }
+}
diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts
new file mode 100644
index 000000000..a495211d4
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts
@@ -0,0 +1,11 @@
+export class MultiSelectItem {
+ id : number;
+ itemId : number;
+ itemName : string;
+
+ constructor(genericId: number, itemId : number, itemName : string){
+ this.id = genericId;
+ this.itemId = itemId;
+ this.itemName = itemName;
+ }
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.spec.ts
index fc2eed4ae..077d849e6 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.spec.ts
@@ -5,6 +5,7 @@ import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.s
import {BasicControlGenerator} from "./basic.control.generator";
import {NgRedux} from '@angular-redux/store';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
+import {FileFormControl} from "../../../models/formControlModels/fileFormControl.model";
class MockAppStore<T> {}
@@ -44,5 +45,41 @@ describe('Basic Control Generator', () => {
const legacyRegionControl: FormControlModel = service.getLegacyRegion(instance);
expect(legacyRegionControl.isVisible).toBeFalsy();
});
+
+ test('sdn-preload checkbox is visible', () => {
+ const instance = {};
+ const sdncPreload: FormControlModel = service.getSDNCControl(instance);
+ expect (sdncPreload.displayName).toEqual('SDN-C pre-load');
+ expect (sdncPreload.value).toBeFalsy();
+ });
+
+ test('given instance, get supp file from getSupplementaryFile ', () => {
+ const instance = {};
+ const suppFileForInstance: FileFormControl = service.getSupplementaryFile(instance);
+ expect(suppFileForInstance.isVisible).toBeTruthy();
+ expect(suppFileForInstance.hiddenFile.length).toBeGreaterThanOrEqual(1);
+ expect(suppFileForInstance.hiddenFile[0].validations[0].validatorName).toEqual("isFileTooBig");
+ });
+
+ test('concatSupplementaryFile add SupplementaryFile control and hidden file', () => {
+
+ //given
+ const instance = {};
+ const controls = [service.getLegacyRegion(instance)];
+ expect(controls).toHaveLength(1);
+
+ //when
+ const result = service.concatSupplementaryFile(controls, instance);
+
+ //then
+ expect(controls).toHaveLength(1); //original controls remain the same
+
+ expect(result.map((control) => {return control.controlName})).toEqual([
+ "legacyRegion",
+ "supplementaryFile",
+ "supplementaryFile_hidden",
+ "supplementaryFile_hidden_content"
+ ]);
+ });
});
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.ts
index cbbff3c39..7ab64753a 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.ts
@@ -1,12 +1,7 @@
import {Injectable} from "@angular/core";
import {DropdownFormControl} from "../../../models/formControlModels/dropdownFormControl.model";
import {FormGroup} from "@angular/forms";
-import {
- CustomValidatorOptions,
- FormControlModel,
- ValidatorModel,
- ValidatorOptions
-} from "../../../models/formControlModels/formControl.model";
+import {CustomValidatorOptions, FormControlModel, ValidatorModel, ValidatorOptions} from "../../../models/formControlModels/formControl.model";
import {InputFormControl} from "../../../models/formControlModels/inputFormControl.model";
import {AppState} from "../../../store/reducers";
import {NgRedux} from "@angular-redux/store";
@@ -21,7 +16,11 @@ import {FormGeneralErrorsService} from "../../formGeneralErrors/formGeneralError
import {Observable, of} from "rxjs";
import {NodeModel} from "../../../models/nodeModel";
import {Constants} from "../../../utils/constants";
+import {FileUnit} from "../../formControls/component/file/fileUnit.enum";
+import {CheckboxFormControl} from "../../../models/formControlModels/checkboxFormControl.model";
+export const SUPPLEMENTARY_FILE = 'supplementaryFile';
+export const SDN_C_PRE_LOAD = 'sdncPreLoad';
@Injectable()
export class BasicControlGenerator {
@@ -237,4 +236,71 @@ export class BasicControlGenerator {
return initialInstanceName;
}
+ concatSupplementaryFile(originalArray: FormControlModel[], vfModuleInstance): FormControlModel[] {
+ let suppFileInput: FileFormControl = <FileFormControl>(this.getSupplementaryFile(vfModuleInstance));
+ return originalArray.concat([suppFileInput], suppFileInput.hiddenFile);
+ }
+
+ getSDNCControl = (instance: any): FormControlModel => {
+ return new CheckboxFormControl({
+ controlName: SDN_C_PRE_LOAD,
+ displayName: 'SDN-C pre-load',
+ dataTestId: 'sdncPreLoad',
+ value: instance ? instance.sdncPreLoad : false,
+ validations: [new ValidatorModel(ValidatorOptions.required, 'is required')]
+ })
+ };
+
+ getSupplementaryFile(instance: any): FileFormControl {
+ return new FileFormControl({
+ controlName: SUPPLEMENTARY_FILE,
+ displayName: 'Supplementary Data File (JSON format)',
+ dataTestId: 'SupplementaryFile',
+ placeHolder: 'Choose file',
+ selectedFile: !_.isNil(instance) ? instance.supplementaryFileName: null,
+ isVisible: true,
+ acceptedExtentions: "application/json",
+ hiddenFile : [new InputFormControl({
+ controlName: SUPPLEMENTARY_FILE + "_hidden",
+ isVisible: false,
+ validations: [new ValidatorModel(CustomValidatorOptions.isFileTooBig, "File size exceeds 5MB.", [FileUnit.MB, 5])]
+ }),
+ new InputFormControl({
+ controlName: SUPPLEMENTARY_FILE + "_hidden_content",
+ isVisible: false,
+ validations: [new ValidatorModel(CustomValidatorOptions.isValidJson,
+ "File is invalid, please make sure a legal JSON file is uploaded using name:value pairs.",[]),
+ new ValidatorModel(CustomValidatorOptions.isStringContainTags,
+ "File is invalid, please remove tags <>.",[])],
+ value: !_.isNil(instance) ? (instance.supplementaryFile_hidden_content): null,
+ })
+ ],
+ onDelete : this.getOnDeleteForSupplementaryFile(),
+ onChange : this.getOnChangeForSupplementaryFile()
+ })
+ };
+
+ private getOnDeleteForSupplementaryFile() {
+ return (form: FormGroup) => {
+ form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
+ form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
+ };
+ }
+
+ private getOnChangeForSupplementaryFile() {
+ return (files: FileList, form: FormGroup) => {
+ if (files.length > 0) {
+ const file = files.item(0);
+ let reader = new FileReader();
+ reader.onload = function (event) {
+ form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(reader.result);
+ form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(file);
+ };
+ reader.readAsText(file);
+ } else {
+ form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
+ form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
+ }
+ };
+ }
}
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/networkGenerator/network.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/networkGenerator/network.control.generator.spec.ts
index 5b64aea9b..0bb278a8e 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/networkGenerator/network.control.generator.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/networkGenerator/network.control.generator.spec.ts
@@ -7,11 +7,7 @@ import {GenericFormService} from "../../generic-form.service";
import {FormBuilder} from "@angular/forms";
import {LogService} from "../../../../utils/log/log.service";
import {FormControlNames, NetworkControlGenerator} from "./network.control.generator";
-import {
- FormControlModel,
- ValidatorModel,
- ValidatorOptions
-} from "../../../../models/formControlModels/formControl.model";
+import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model";
import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service";
class MockAppStore<T> {
@@ -25,9 +21,6 @@ class MockAppStore<T> {
"FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true,
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/service.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/service.control.generator.spec.ts
index a6a29d1df..6bcec09c4 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/service.control.generator.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/service.control.generator.spec.ts
@@ -25,9 +25,6 @@ class MockAppStore<T> {
"FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true,
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts
index 351f8393c..deb1a784a 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts
@@ -1,18 +1,16 @@
import {getTestBed, TestBed} from '@angular/core/testing';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {NgRedux} from '@angular-redux/store';
-import {BasicControlGenerator} from "../basic.control.generator";
+import {BasicControlGenerator, SDN_C_PRE_LOAD} from "../basic.control.generator";
import {AaiService} from "../../../../services/aaiService/aai.service";
import {GenericFormService} from "../../generic-form.service";
import {FormBuilder} from "@angular/forms";
import {LogService} from "../../../../utils/log/log.service";
-import {
- FormControlModel,
- ValidatorModel,
- ValidatorOptions
-} from "../../../../models/formControlModels/formControl.model";
+import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model";
import {FormControlNames, VfModuleControlGenerator} from "./vfModule.control.generator";
import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service";
+import {VfModuleInstance} from "../../../../models/vfModuleInstance";
+import {VfModule} from "../../../../models/vfModule";
class MockAppStore<T> {
getState() {
@@ -25,9 +23,6 @@ class MockAppStore<T> {
"FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true,
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
@@ -978,6 +973,46 @@ describe('VFModule Control Generator', () => {
}
});
+
+ const cases = [
+ [true, true, true, null, true, true],
+ [true, true, false, null, true, false], //Scenario to check that UI field doesn't appear.
+ [false, true, false, "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0_vol", true, true],
+ [false, true, true, "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0_vol", true, true],
+ [false, false, true, null, false, false],
+ ];
+
+ test.each(cases)('Given Ecomp Gen Name: %p and VG Name %p , ' +
+ 'is A La Carte %p - expect the name value for VG to be %p , ' +
+ 'VG Name should be defined: %p , and should the field be visible: %p',
+ (ecomGenName, vGName, isALaCarte, expectedName, shouldWeVerifyDefinitionOfField, isVisible) => {
+ const moduleName = "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0";
+ service.vfModuleModel = new VfModule();
+ service.vfModuleModel.name = moduleName;
+ service.vfModuleModel.volumeGroupAllowed = vGName;
+ let vnf : Object = {isEcompGeneratedNaming: ecomGenName};
+ const serviceId: string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44";
+ const vnfStoreKey: string = 'VF_vGeraldine 0';
+ const uuidData: Object = {
+ modelName : moduleName,
+ vFModuleStoreKey : "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0vmvzo",
+ };
+ const vfModuleModel :VfModuleInstance = service.getVfModuleInstance(serviceId, vnfStoreKey, uuidData,true);
+ let existingMatchingFieldInForm = buildVfModuleFormControlModel(vfModuleModel ,serviceId, vnf, isALaCarte);
+ if (shouldWeVerifyDefinitionOfField) {
+ expect(existingMatchingFieldInForm).toBeDefined();
+ expect(existingMatchingFieldInForm.value).toEqual(expectedName);
+ expect(existingMatchingFieldInForm.isVisible).toEqual(isVisible);
+ } else {
+ expect(existingMatchingFieldInForm).toBeUndefined();
+ }
+ });
+
+ let buildVfModuleFormControlModel = function(vfModuleModel :any, serviceId: string, vnf, isALaCarte) :FormControlModel {
+ let controls: FormControlModel[] = service.pushInstanceAndVGToForm([], vfModuleModel, serviceId, vnf, isALaCarte);
+ return controls.find(ctrl => ctrl.controlName === FormControlNames.VOLUME_GROUP_NAME);
+ };
+
test('getMacroFormControls check for mandatory controls', () => {
const serviceId: string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44";
const vnfStoreKey: string = 'VF_vGeraldine 0';
@@ -1022,7 +1057,7 @@ describe('VFModule Control Generator', () => {
FormControlNames.LEGACY_REGION,
FormControlNames.TENANT_ID,
FormControlNames.ROLLBACK_ON_FAILURE,
- FormControlNames.SDN_C_PRE_LOAD
+ SDN_C_PRE_LOAD,
];
expect(controls.length).toEqual(7);
@@ -1057,7 +1092,7 @@ describe('VFModule Control Generator', () => {
FormControlNames.TENANT_ID, // TENANT_ID must be after LEGACY_REGION
FormControlNames.LEGACY_REGION,
FormControlNames.ROLLBACK_ON_FAILURE,
- FormControlNames.SDN_C_PRE_LOAD
+ SDN_C_PRE_LOAD,
];
for(let i = 0 ; i < orderedControls.length ; i++) {
@@ -1114,7 +1149,7 @@ describe('VFModule Control Generator', () => {
FormControlNames.LEGACY_REGION,
FormControlNames.TENANT_ID,
FormControlNames.ROLLBACK_ON_FAILURE,
- FormControlNames.SDN_C_PRE_LOAD
+ SDN_C_PRE_LOAD,
];
for(let i = 0 ; i < orderedControls.length ; i++) {
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts
index 3012c139c..8919c0419 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts
@@ -37,8 +37,6 @@ export enum FormControlNames {
LEGACY_REGION = 'legacyRegion',
TENANT_ID = 'tenantId',
ROLLBACK_ON_FAILURE = 'rollbackOnFailure',
- SDN_C_PRE_LOAD = 'sdncPreLoad',
- SUPPLEMENTARY_FILE = 'supplementaryFile'
}
@@ -46,7 +44,6 @@ export enum FormControlNames {
export class VfModuleControlGenerator {
aaiService: AaiService;
vfModuleModel: VfModule;
- vfModuleName : string;
isUpdateMode : boolean;
constructor(private genericFormService: GenericFormService,
@@ -63,7 +60,6 @@ export class VfModuleControlGenerator {
const vfModulesKeys = Object.keys(vfModules);
for(let key of vfModulesKeys){
if(vfModules[key].uuid === vfModuleUuid){
- this.vfModuleName = key;
return;
}
}
@@ -105,15 +101,18 @@ export class VfModuleControlGenerator {
let result: FormControlModel[] = [];
if (!_.isNil(vfModuleModel)) {
- result.push(this.getInstanceName(vfModuleInstance, serviceId, vnfModel.isEcompGeneratedNaming));
- if (this.vfModuleModel.volumeGroupAllowed) {
- result.push(this.getVolumeGroupName(vfModuleInstance, serviceId, vnfStoreKey, vfModuleInstance && vfModuleInstance.volumeGroupName, vnfModel.isEcompGeneratedNaming));
- }
+ result = this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, false);
}
if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
- let suppFileInput:FileFormControl = <FileFormControl>(this.getSupplementaryFile(vfModuleInstance));
- result.push(suppFileInput);
- result = result.concat(suppFileInput.hiddenFile);
+ result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance);
+ }
+ return result;
+ }
+
+ pushInstanceAndVGToForm(result: FormControlModel[], vfModuleElement: any, serviceId: string, vnfModel: any, isALaCarte: boolean) :FormControlModel[]{
+ result.push(this.getInstanceName(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming));
+ if (this.vfModuleModel.volumeGroupAllowed) {
+ result.push(this.getVolumeGroupData(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming, isALaCarte));
}
return result;
}
@@ -133,23 +132,16 @@ export class VfModuleControlGenerator {
const vfModuleInstance = this.getVfModuleInstance(serviceId, vnfStoreKey, uuidData, isUpdateMode);
let result: FormControlModel[] = [];
- result.push(this.getInstanceName(vfModuleInstance, serviceId, vnfModel.isEcompGeneratedNaming));
-
- if (this.vfModuleModel.volumeGroupAllowed) {
- result.push(this.getVolumeGroupName(vfModuleInstance, serviceId, vnfStoreKey, this.vfModuleName, vnfModel.isEcompGeneratedNaming));
- }
+ this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, true);
result.push(this.getLcpRegionControl(serviceId, vfModuleInstance, result));
result.push(this._basicControlGenerator.getLegacyRegion(vfModuleInstance));
result.push(this.getTenantControl(serviceId, vfModuleInstance, result));
result.push(this.getRollbackOnFailureControl(vfModuleInstance, result));
- result.push(this.getSDNCControl(vfModuleInstance, result));
+ result.push(this._basicControlGenerator.getSDNCControl(vfModuleInstance));
if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
- let suppFileInput:FileFormControl = <FileFormControl>(this.getSupplementaryFile(vfModuleInstance));
- result.push(suppFileInput);
- result = result.concat(suppFileInput.hiddenFile);
+ result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance);
}
return result;
-
}
getInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): FormControlModel {
@@ -163,7 +155,7 @@ export class VfModuleControlGenerator {
return formControlModel;
}
- getDefaultVolumeGroupName(instance: any, vfModuleName: string, isEcompGeneratedNaming: boolean): string {
+ getDefaultVolumeGroupName(instance: any, isEcompGeneratedNaming: boolean): string {
if ((!_.isNil(instance) && instance.volumeGroupName)) {
return instance.volumeGroupName;
}
@@ -173,7 +165,7 @@ export class VfModuleControlGenerator {
return this._basicControlGenerator.getDefaultInstanceName(instance, this.vfModuleModel) + "_vol";
}
- getVolumeGroupName(instance: any, serviceId: string, vnfStoreKey: string, vfModuleName: string, isEcompGeneratedNaming: boolean): FormControlModel {
+ getVolumeGroupData(instance: any, serviceId: string, isEcompGeneratedNaming: boolean, isALaCarte: boolean): FormControlModel {
let validations: ValidatorModel[] = [
new ValidatorModel(ValidatorOptions.pattern, 'Instance name may include only alphanumeric characters and underscore.', BasicControlGenerator.INSTANCE_NAME_REG_EX),
new ValidatorModel(CustomValidatorOptions.uniqueInstanceNameValidator, 'Volume Group instance name is already in use, please pick another name', [this.store, serviceId, instance && instance.volumeGroupName])
@@ -190,8 +182,8 @@ export class VfModuleControlGenerator {
validations: validations,
tooltip : 'When filled, VID will create a Volume Group by this name and associate with this module.\n' +
'When empty, the module is created without a Volume Group.',
- isVisible: true,
- value: this.getDefaultVolumeGroupName(instance, vfModuleName, isEcompGeneratedNaming),
+ isVisible: this.shouldVGNameBeVisible(isEcompGeneratedNaming,isALaCarte),
+ value: this.getDefaultVolumeGroupName(instance, isEcompGeneratedNaming),
onKeypress: (event) => {
const pattern:RegExp = BasicControlGenerator.INSTANCE_NAME_REG_EX;
if (pattern) {
@@ -204,51 +196,13 @@ export class VfModuleControlGenerator {
});
}
- getSupplementaryFile(instance: any): FormControlModel {
- return new FileFormControl({
- controlName: FormControlNames.SUPPLEMENTARY_FILE,
- displayName: 'Supplementary Data File (JSON format)',
- dataTestId: 'SupplementaryFile',
- placeHolder: 'Choose file',
- selectedFile: !_.isNil(instance) ? instance.supplementaryFileName: null,
- isVisible: true,
- acceptedExtentions: "application/json",
- hiddenFile : [new InputFormControl({
- controlName: FormControlNames.SUPPLEMENTARY_FILE + "_hidden",
- isVisible: false,
- validations: [new ValidatorModel(CustomValidatorOptions.isFileTooBig, "File size exceeds 5MB.", [FileUnit.MB, 5])]
- }),
- new InputFormControl({
- controlName: FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content",
- isVisible: false,
- validations: [new ValidatorModel(CustomValidatorOptions.isValidJson,
- "File is invalid, please make sure a legal JSON file is uploaded using name:value pairs.",[]),
- new ValidatorModel(CustomValidatorOptions.isStringContainTags,
- "File is invalid, please remove tags <>.",[])],
- value: !_.isNil(instance) ? (instance.supplementaryFile_hidden_content): null,
- })
- ],
- onDelete : (form : FormGroup) => {
- form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
- form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
- },
- onChange : (files: FileList, form : FormGroup) => {
- if (files.length > 0) {
- const file = files.item(0);
- let reader = new FileReader();
- reader.onload = function(event) {
- form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content"].setValue(reader.result);
- form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden"].setValue(file);
- };
- reader.readAsText(file);
- }
- else {
- form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
- form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
- }
- }
- })
- };
+ private shouldVGNameBeVisible(isEcompGeneratedNaming: boolean, isALaCarte: boolean) {
+ if((!isALaCarte && !isEcompGeneratedNaming) || isALaCarte){
+ return true;
+ }
+ return false;
+
+ }
getTenantControl = (serviceId: string, instance: any, controls: FormControlModel[]): DropdownFormControl => {
const service = this.store.getState().service.serviceInstance[serviceId];
@@ -316,17 +270,6 @@ export class VfModuleControlGenerator {
})
};
- getSDNCControl = (instance: any, controls: FormControlModel[]): CheckboxFormControl => {
- return new CheckboxFormControl({
- type: FormControlType.CHECKBOX,
- controlName: 'sdncPreLoad',
- displayName: 'SDN-C pre-load',
- dataTestId: 'sdncPreLoad',
- value: instance ? instance.sdncPreLoad : false,
- validations: [new ValidatorModel(ValidatorOptions.required, 'is required')]
- })
- };
-
getRollbackOnFailureControl = (instance: any, controls: FormControlModel[]): DropdownFormControl => {
return new DropdownFormControl({
type: FormControlType.DROPDOWN,
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts
index 66afac9ad..28d49d51b 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts
@@ -6,16 +6,13 @@ import {BasicControlGenerator} from "../basic.control.generator";
import {AaiService} from "../../../../services/aaiService/aai.service";
import {GenericFormService} from "../../generic-form.service";
import {FormBuilder} from "@angular/forms";
-import {
- FormControlModel,
- ValidatorModel,
- ValidatorOptions
-} from "../../../../models/formControlModels/formControl.model";
+import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model";
import {LogService} from "../../../../utils/log/log.service";
import {VnfControlGenerator} from "./vnf.control.generator";
import {Observable} from "rxjs";
import {SelectOption} from "../../../../models/selectOption";
import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service";
+import {FormControlType} from "../../../../models/formControlModels/formControlTypes.enum";
class MockAppStore<T> {
getState(){
@@ -28,9 +25,6 @@ class MockAppStore<T> {
"FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true,
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
@@ -941,6 +935,18 @@ describe('VNF Control Generator', () => {
})().then(done).catch(done.fail));
+ test('should generate platform multi select control', ()=>{
+ const control = service.getPlatformMultiselectControl(null, [],false);
+ expect(control.type).toEqual(FormControlType.MULTI_SELECT);
+ expect(control.controlName).toEqual('platformName');
+ expect(control.displayName).toEqual('Platform');
+ expect(control.dataTestId).toEqual('multi-selectPlatform');
+ expect(control.selectedFieldName).toEqual('name');
+ expect(control.value).toEqual('');
+ expect(control.onChange).toBeDefined();
+ expect(control.convertOriginalDataToArray).toBeDefined();
+ });
+
test('getMacroFormControls check for mandatory controls', () => {
const serviceId : string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44";
const vnfName : string = "VF_vGeraldine 0";
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts
index 7760ba8ad..ff0a525b5 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts
@@ -15,11 +15,12 @@ import {AppState} from "../../../../store/reducers";
import {FormGroup} from "@angular/forms";
import {DropdownFormControl} from "../../../../models/formControlModels/dropdownFormControl.model";
import {FormControlType} from "../../../../models/formControlModels/formControlTypes.enum";
-import {InputFormControl} from "../../../../models/formControlModels/inputFormControl.model";
import {Observable, of} from "rxjs";
import {SelectOption} from "../../../../models/selectOption";
import * as _ from 'lodash';
import {Constants} from "../../../../utils/constants";
+import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model";
+import {MultiSelectItem} from "../../../formControls/component/multiselect/multiselect.model";
export enum FormControlNames {
INSTANCE_NAME = 'instanceName',
@@ -76,6 +77,7 @@ export class VnfControlGenerator {
const vnfInstance = this.getVnfInstance(serviceId, vnfStoreKey);
const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfName]);
let result: FormControlModel[] = [];
+ const flags = this.store.getState().global.flags;
if (!_.isNil(vnfModel)) {
result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming));
@@ -83,7 +85,7 @@ export class VnfControlGenerator {
result.push(this.getLcpRegionControl(serviceId, vnfInstance, result));
result.push(this._basicControlGenerator.getLegacyRegion(vnfInstance));
result.push(this.getTenantControl(serviceId, vnfInstance, result));
- result.push(this.getPlatformControl(vnfInstance, result));
+ result.push(this.getPlatformMultiselectControl(vnfInstance, result, flags['FLAG_2002_VNF_PLATFORM_MULTI_SELECT']));
result.push(this.getLineOfBusinessControl(vnfInstance, result));
}
return result;
@@ -101,12 +103,13 @@ export class VnfControlGenerator {
const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfName]);
if (!_.isNil(vnfModel)) {
+ const flags = this.store.getState().global.flags;
result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming));
result.push(this._basicControlGenerator.getProductFamilyControl(vnfInstance, result, false));
result.push(this.getLcpRegionControl(serviceId, vnfInstance, result));
result.push(this._basicControlGenerator.getLegacyRegion(vnfInstance));
result.push(this.getTenantControl(serviceId, vnfInstance, result));
- result.push(this.getPlatformControl(vnfInstance, result));
+ result.push(this.getPlatformMultiselectControl(vnfInstance, result, flags['FLAG_2002_VNF_PLATFORM_MULTI_SELECT']));
result.push(this.getLineOfBusinessControl(vnfInstance, result));
result.push(this.getRollbackOnFailureControl(vnfInstance, result));
}
@@ -139,20 +142,34 @@ export class VnfControlGenerator {
})
};
- getPlatformControl = (instance: any, controls: FormControlModel[]): DropdownFormControl => {
- return new DropdownFormControl({
- type: FormControlType.DROPDOWN,
+
+
+ getPlatformMultiselectControl = (instance: any, controls: FormControlModel[], isMultiSelected: boolean) : MultiselectFormControl => {
+ return new MultiselectFormControl({
+ type: FormControlType.MULTI_SELECT ,
controlName: 'platformName',
displayName: 'Platform',
- dataTestId: 'platform',
+ dataTestId: 'multi-selectPlatform',
+ selectedFieldName : 'name' ,
+ ngValue : 'name',
placeHolder: 'Select Platform',
isDisabled: false,
name: "platform",
- value: instance ? instance.platformName : null,
+ value: instance ? instance.platformName : '',
+ limitSelection : isMultiSelected ? 1000 : 1,
validations: [new ValidatorModel(ValidatorOptions.required, 'is required')],
onInitSelectedField: ['platformList'],
- onInit: this._basicControlGenerator.getSubscribeInitResult.bind(null, this._aaiService.getCategoryParameters)
- })
+ onInit: this._basicControlGenerator.getSubscribeInitResult.bind(null, this._aaiService.getCategoryParameters),
+ onChange : (param: MultiSelectItem[], form: FormGroup) => {
+ form.controls['platformName'].setValue(param.map((multiSelectItem: MultiSelectItem)=>{
+ return multiSelectItem.itemName
+ }).join(','));
+ },
+ convertOriginalDataToArray : (value?: string) => {
+ if(_.isNil(value)) return [];
+ return value.split(',');
+ }
+ });
};
getTenantControl = (serviceId: string, instance: any, controls: FormControlModel[]): DropdownFormControl => {
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator.spec.ts
index 71d661191..81cfd9614 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator.spec.ts
@@ -6,11 +6,7 @@ import {BasicControlGenerator} from "../basic.control.generator";
import {AaiService} from "../../../../services/aaiService/aai.service";
import {GenericFormService} from "../../generic-form.service";
import {FormBuilder} from "@angular/forms";
-import {
- FormControlModel,
- ValidatorModel,
- ValidatorOptions
-} from "../../../../models/formControlModels/formControl.model";
+import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model";
import {LogService} from "../../../../utils/log/log.service";
import {VnfGroupControlGenerator} from "./vnfGroup.control.generator";
import {Observable} from "rxjs";
@@ -25,19 +21,14 @@ class MockAppStore<T> {
"type": "UPDATE_DRAWING_BOARD_STATUS",
"drawingBoardStatus": "CREATE",
"flags": {
- "CREATE_INSTANCE_TEST": false,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true,
"FLAG_SERVICE_MODEL_CACHE": false,
"FLAG_SHOW_ASSIGNMENTS": true,
"FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true,
- "FLAG_DEFAULT_VNF": true,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true,
"FLAG_A_LA_CARTE_AUDIT_INFO": true,
"FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true,
"FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true,
- "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true,
"FLAG_1902_NEW_VIEW_EDIT": true
}
},
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html
index d4c5118b3..edf86823c 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html
+++ b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html
@@ -6,6 +6,11 @@
<checkbox-form-control *ngSwitchCase="'CHECKBOX'" [data]="formControl" [form]="dynamicFormGroup" ></checkbox-form-control>
<dropdown-form-control *ngSwitchCase="'DROPDOWN'" [data]="formControl" [form]="dynamicFormGroup" ></dropdown-form-control>
<file-form-control *ngSwitchCase="'FILE'" [data]="formControl" [form]="dynamicFormGroup"></file-form-control>
+ <multiselect-form-control *ngSwitchCase="'MULTI_SELECT'"
+ [data]="formControl"
+ [form]="dynamicFormGroup"
+ [multiselectOptions]="formControl?.options$"
+ [selectedItems]="formControl.value"></multiselect-form-control>
</div>
<div *ngIf="dynamicFormGroup != null && formControl != null && dynamicFormGroup.controls[formControl.controlName]?.errors">
<div *ngFor="let validatorModel of formControl?.validations">
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html
index 57064f658..f9a11eab1 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html
@@ -3,14 +3,13 @@
<div class="modal-header">
<button type="button"
class="close"
- (click)="formPopupDetails?.onCancel(formPopupDetails.that,dynamicForm)" >&times;
+ (click)="formPopupDetails?.onCancel(formPopupDetails.that,dynamicForm)">&times;
</button>
<span [attr.data-tests-id]="'create-modal-title'"
class="modal-title">{{formPopupDetails?.title}}
</span>
</div>
<div class="modal-body popup-content">
-
<div class="header-left">
<div>MODEL: <span>"{{formPopupDetails?.leftSubTitle}}"</span></div>
</div>
@@ -36,12 +35,14 @@
<model-information [modelInformationItems]="formPopupDetails?.modelInformationItems"></model-information>
</div>
- <div class="instance-form">
+ <div class="instance-form">
<div style="position: relative;height: 100%;overflow: auto;">
- <label id="notification-area" *ngIf="shouldShowNotification() == true" style="color: #959595;font-size: 12px;left: 30px;margin-left: 30px;">Data entered will apply to all service instances</label>
- <generic-form [formControls]="formPopupDetails?.formControlList"
- [dynamicInputs]="formPopupDetails?.dynamicInputsControlList"
- (onFormChanged)="dynamicForm = $event" ></generic-form>
+ <label id="notification-area" *ngIf="shouldShowNotification() == true"
+ style="color: #959595;font-size: 12px;left: 30px;margin-left: 30px;">Data entered will apply to all
+ service instances</label>
+ <generic-form [formControls]="formPopupDetails?.formControlList"
+ [dynamicInputs]="formPopupDetails?.dynamicInputsControlList"
+ (onFormChanged)="dynamicForm = $event"></generic-form>
</div>
</div>
@@ -54,6 +55,19 @@
</div>
<div class="col-md-6" style="padding: 15px;padding-right: 35px;">
<button
+ *ngIf="showTemplateBtn"
+ [attr.data-tests-id]="'templateButton'"
+ type="button" class="btn btn-success submit"
+ (click)="openTemplateModal()"
+ ><span>Template</span></button>
+ <button
+ *ngIf="isShowPreviousInstantiationBtn"
+ [attr.data-tests-id]="'ShowPreviousInstancesButton'"
+ type="button" class="btn btn-success submit"
+ (click)="formPopupDetails.onOtherAction(formPopupDetails.that, dynamicForm)">
+ <span>Previous Instantiation</span>
+ </button>
+ <button
[attr.data-tests-id]="'cancelButton'"
type="button" class="btn btn-default cancel"
(click)="formPopupDetails.onCancel(formPopupDetails.that, dynamicForm)"><span>Cancel</span></button>
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss
index 5057b44a5..18416dae6 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss
@@ -134,7 +134,7 @@ $grid-border: 1px #d2d2d2 solid;
}
.submit {
- width: 120px;
+ min-width: 120px;
height: 36px;
background: #009fdb;
border-radius: 2px;
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts
index 8a95d108f..3939e44ff 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts
@@ -13,55 +13,62 @@ import {AaiService} from "../../services/aaiService/aai.service";
import {GenericFormPopupService} from "./generic-form-popup.service";
import {FormControlModel} from "../../models/formControlModels/formControl.model";
import {FormGeneralErrorsService} from "../formGeneralErrors/formGeneralErrors.service";
+import {FeatureFlagsService, Features} from "../../services/featureFlag/feature-flags.service";
+import {InstantiationTemplatesModalComponent} from "./instantiationTemplatesModal/instantiation.templates.modal.component";
export interface PopupModel {
- type : PopupType;
- uuidData : UUIDData;
- node : ITreeNode;
- isUpdateMode : boolean;
+ type: PopupType;
+ uuidData: UUIDData;
+ node: ITreeNode;
+ isUpdateMode: boolean;
}
-export enum PopupType{
+export enum PopupType {
SERVICE = 'service',
VNF = 'vnf',
NETWORK = 'network',
VF_MODULE = 'vf_module',
+ VF_MODULE_UPGRADE = 'vf_module_upgrade',
VNF_GROUP = 'vnf_group'
}
@Component({
- selector : 'generic-form-popup',
- templateUrl : 'generic-form-popup.component.html',
- styleUrls : ['generic-form-popup.component.scss']
+ selector: 'generic-form-popup',
+ templateUrl: 'generic-form-popup.component.html',
+ styleUrls: ['generic-form-popup.component.scss']
})
-export class GenericFormPopupComponent extends DialogComponent<PopupModel, boolean> implements OnInit, OnDestroy{
- formPopupDetails : FormPopupDetails = null;
- dynamicForm : FormGroup;
- type : PopupType;
- uuidData : UUIDData;
- isUpdateMode : boolean;
- node : ITreeNode = null;
- hasGeneralApiError : boolean = false;
+export class GenericFormPopupComponent extends DialogComponent<PopupModel, boolean> implements OnInit, OnDestroy {
+ formPopupDetails: FormPopupDetails = null;
+ dynamicForm: FormGroup;
+ type: PopupType;
+ uuidData: UUIDData;
+ showTemplateBtn: boolean = false;
+ isShowPreviousInstantiationBtn: boolean = false;
+ isUpdateMode: boolean;
+ node: ITreeNode = null;
+ hasGeneralApiError: boolean = false;
parentElementClassName = 'content';
errorMsg = 'Page contains errors. Please see details next to the relevant fields.';
servicesQty = 1;
quantityOptions = _.range(1, 51)
- constructor(dialogService: DialogService ,
- private _iframeService : IframeService,
+
+ constructor(dialogService: DialogService,
+ private _iframeService: IframeService,
private _store: NgRedux<AppState>,
- private _servicePopupService : ServicePopupService,
- private _activatedRoute : ActivatedRoute,
- private _aaiService : AaiService,
+ private _servicePopupService: ServicePopupService,
+ private _activatedRoute: ActivatedRoute,
+ private _aaiService: AaiService,
+ private _dialogService: DialogService,
private _route: ActivatedRoute,
- private _genericFormPopupService : GenericFormPopupService){
+ private _genericFormPopupService: GenericFormPopupService) {
super(dialogService);
}
- closeDialog(that) : void{
+ closeDialog(that): void {
this._iframeService.removeClassCloseModal(that.parentElementClassName);
this.dialogService.removeDialog(this);
setTimeout(() => {
@@ -69,7 +76,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
}, 15);
}
- shouldShowNotification() : boolean {
+ shouldShowNotification(): boolean {
return this.formPopupDetails && this.formPopupDetails.UUIDData['bulkSize'] > 1
}
@@ -78,38 +85,17 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
.queryParams
.subscribe(params => {
console.log('changed');
- if(params['serviceModelId'] && params['isCreate']=="true"){
- this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId : string)=>{
- this.uuidData = <any>{
- bulkSize : 1,
- isMacro : this._store.getState().service.serviceHierarchy[serviceModelId].service.vidNotions.instantiationType === 'Macro',
- type : PopupType.SERVICE,
- serviceId: serviceModelId,
- popupService: this._servicePopupService,
- };
-
- this.uuidData.popupService.closeDialogEvent.subscribe((that)=>{
- this.closeDialog(that);
- });
-
- this.formPopupDetails = this.uuidData.popupService.getGenericFormPopupDetails(
- this.uuidData['serviceId'],
- null,
- null,
- this.node,
- this.uuidData,
- false
- );
- });
+ if (params['serviceModelId'] && params['isCreate'] == "true") {
+ this.onInitForCreateNewServicePopup();
}
});
- FormGeneralErrorsService.checkForErrorTrigger.subscribe(()=>{
+ FormGeneralErrorsService.checkForErrorTrigger.subscribe(() => {
this.hasSomeError(this.formPopupDetails, this.dynamicForm);
});
-
- if(!_.isNil(this.uuidData)){
- this.uuidData.popupService.closeDialogEvent.subscribe((that)=>{
+
+ if (!_.isNil(this.uuidData)) {
+ this.uuidData.popupService.closeDialogEvent.subscribe((that) => {
this.closeDialog(that);
});
@@ -118,28 +104,62 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
}
}
- hasSomeError(formPopupDetails : FormPopupDetails, form : FormGroup) : boolean{
- if(_.isNil(formPopupDetails)) return false;
+ private onInitForCreateNewServicePopup() {
+ this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId: string) => {
+ this.uuidData = <any>{
+ bulkSize: 1,
+ isMacro: this._store.getState().service.serviceHierarchy[serviceModelId].service.vidNotions.instantiationType === 'Macro',
+ type: PopupType.SERVICE,
+ serviceId: serviceModelId,
+ popupService: this._servicePopupService,
+ };
+ this.showTemplateBtn = !!this._store.getState().global.flags["FLAG_2004_INSTANTIATION_TEMPLATES_POPUP"];
+
+ this.isShowPreviousInstantiationBtn = !!this._store.getState().global.flags["FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER"];
+
+ this.uuidData.popupService.closeDialogEvent.subscribe((that) => {
+ this.closeDialog(that);
+ });
+
+ this.formPopupDetails = this.uuidData.popupService.getGenericFormPopupDetails(
+ this.uuidData['serviceId'],
+ null,
+ null,
+ this.node,
+ this.uuidData,
+ false
+ );
+ });
+ }
+
+ hasSomeError(formPopupDetails: FormPopupDetails, form: FormGroup): boolean {
+ if (_.isNil(formPopupDetails)) return false;
else {
- for(let controlName in form.controls){
- if(form.controls[controlName].errors){
+ for (let controlName in form.controls) {
+ if (form.controls[controlName].errors) {
let error: string[] = Object.keys(form.controls[controlName].errors);
- if(error.length === 1 && error[0] === 'required'){
+ if (error.length === 1 && error[0] === 'required') {
continue;
- }else if(Object.keys(form.controls[controlName].errors).length > 0 ){
+ } else if (Object.keys(form.controls[controlName].errors).length > 0) {
return true;
}
}
}
}
- return formPopupDetails.formControlList.filter((item : FormControlModel) => item.type === 'DROPDOWN' && item['hasEmptyOptions'] && item.isRequired()).length > 0
+ return formPopupDetails.formControlList.filter((item: FormControlModel) => item.type === 'DROPDOWN' && item['hasEmptyOptions'] && item.isRequired()).length > 0
}
+
+
+ openTemplateModal = (): void => {
+ this._dialogService.addDialog(InstantiationTemplatesModalComponent, {});
+ }
+
}
-export class UUIDData extends Object{
- type : string;
- popupService : any;
+export class UUIDData extends Object {
+ type: string;
+ popupService: any;
}
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts
index fa77bed5f..63c980cd5 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts
@@ -20,6 +20,7 @@ import {NetworkControlGenerator} from "../genericForm/formControlsServices/netwo
import {VfModulePopuopService} from "./genericFormServices/vfModule/vfModule.popuop.service";
import {VfModuleControlGenerator} from "../genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator";
import {FeatureFlagsService} from "../../services/featureFlag/feature-flags.service";
+import {VfModuleUpgradePopupService} from "./genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
class MockAppStore<T>{
getState() {
@@ -32,9 +33,6 @@ class MockAppStore<T>{
"FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true,
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
@@ -970,6 +968,7 @@ describe('Generic Form popup Service', () => {
NetworkPopupService,
NetworkControlGenerator,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
VfModuleControlGenerator,
{provide:FeatureFlagsService, useClass: MockFeatureFlagsService},
{provide: ActivatedRoute, useClass: ActivatedRouteMock},
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts
index 54af063d8..a3c83263c 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts
@@ -33,10 +33,7 @@ class MockReduxStore<T> {
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
"FLAG_ADVANCED_PORTS_FILTER": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
"FLAG_REGION_ID_FROM_REMOTE": true,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts
index 5d4d16567..1d44a9e5e 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts
@@ -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);
+ return new VfModule(rawModel, flags);
}
case 'networks' : {
- return new NetworkModel(rawModel);
+ return new NetworkModel(rawModel, flags);
}
case 'vnfGroups' : {
return new VnfGroupModel(rawModel);
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts
index eb094abfb..67c371212 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts
@@ -30,10 +30,7 @@ class MockReduxStore<T> {
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
"FLAG_ADVANCED_PORTS_FILTER": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
"FLAG_REGION_ID_FROM_REMOTE": true,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts
index 5b5acd33b..ebea695f7 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts
@@ -31,10 +31,7 @@ class MockReduxStore<T> {
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
"FLAG_ADVANCED_PORTS_FILTER": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
"FLAG_REGION_ID_FROM_REMOTE": true,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
@@ -2143,6 +2140,33 @@ describe('Service popup service', () => {
expect(service.closeDialogEvent.next).toHaveBeenCalledWith(that);
});
+ test('showPreviousInstantiations should trigger postMessage', () => {
+ let that = <any>{
+ parentElementClassName: 'content',
+ _iframeService: iframeService,
+ resetPopupData : () =>{ },
+ serviceModel:{
+ uuid:'1111'
+ }
+
+ };
+
+ let expectedMessage= {
+ eventId: 'showPreviousInstantiations',
+ data: {
+ serviceModelId: that.serviceModel.uuid
+ }
+ };
+
+ jest.spyOn(window.parent, 'postMessage');
+
+ service.showPreviousInstantiations(that, fb.group({}));
+
+ expect( window.parent.postMessage).toHaveBeenCalledWith(expectedMessage,"*")
+
+ });
+
+
test('getDynamicInputs should return list of controls' ,() => {
const result: FormControlModel[] = service.getDynamicInputs('6b528779-44a3-4472-bdff-9cd15ec93450');
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts
index 7694e6314..3e7e8c1e5 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts
@@ -20,6 +20,7 @@ import {ModelInfo} from "../../../../models/modelInfo";
import {FormControlModel} from "../../../../models/formControlModels/formControl.model";
import {createServiceInstance, updateServiceInstance} from "../../../../storeUtil/utils/service/service.actions";
import * as _ from 'lodash';
+import {Utils} from "../../../../utils/utils";
@Injectable()
export class ServicePopupService implements GenericPopupInterface {
@@ -58,7 +59,12 @@ export class ServicePopupService implements GenericPopupInterface {
this.getDynamicInputs(serviceId),
this.modelInformations,
(that, form: FormGroup) => {that.onSubmit(that, form);},
- (that: any, form: FormGroup) => {that.onCancel(that, form); }
+ (that: any, form: FormGroup) => {
+ that.onCancel(that, form);
+ },
+ (that: any, form: FormGroup) => {
+ that.showPreviousInstantiations(that, form);
+ }
);
}
@@ -122,13 +128,24 @@ export class ServicePopupService implements GenericPopupInterface {
onSubmit(that, form: FormGroup, ...args): void {
form = that.updateExtraValues(that, form);
that.storeServiceInstance(form.value, args[0], [], new ModelInfo(that.serviceModel), that.serviceModel);
- window.parent.postMessage( {
- eventId: 'submitIframe',
+ const eventId = 'submitIframe';
+ this.postMessageToWindowParent(eventId, that.serviceModel.uuid);
+ this.onCancel(that, form);
+ }
+
+ showPreviousInstantiations(that, form: FormGroup,): void {
+ const eventId = 'showPreviousInstantiations';
+ this.postMessageToWindowParent(eventId, that.serviceModel.uuid);
+ this.onCancel(that, form);
+ }
+
+ private postMessageToWindowParent(eventId: string, serviceModelId:string) {
+ window.parent.postMessage({
+ eventId: eventId,
data: {
- serviceModelId: that.serviceModel.uuid
+ serviceModelId
}
}, "*");
- this.onCancel(that, form);
}
updateExtraValues = (that, form) : any => {
@@ -163,13 +180,13 @@ export class ServicePopupService implements GenericPopupInterface {
this._store.dispatch(updateServiceInstance(formValues, serviceModel.modelVersionId));
}
- if (this._store.getState().global.flags['FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD'] && isCreateMode) {
+ if (isCreateMode) {
this._defaultDataGeneratorService.updateReduxOnFirstSet(serviceModel.modelVersionId, formValues);
}
};
setIsALaCarte = (formValues: any, instantiationType) => {
- formValues.isALaCarte = instantiationType === 'ALaCarte';
+ formValues.isALaCarte = Utils.isALaCarte(instantiationType);
};
setTestApi = (formValues: any) =>{
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.spec.ts
index 5b27b6e29..6c487102f 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.spec.ts
@@ -30,10 +30,7 @@ class MockReduxStore<T> {
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
"FLAG_ADVANCED_PORTS_FILTER": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
"FLAG_REGION_ID_FROM_REMOTE": true,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.ts
index c7a71efc0..20336e5eb 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.ts
@@ -21,8 +21,7 @@ import {FormControlModel} from "../../../../models/formControlModels/formControl
import * as _ from 'lodash';
import {createVFModuleInstance, updateVFModuleInstance} from "../../../../storeUtil/utils/vfModule/vfModule.actions";
-@Injectable()
-export class VfModulePopuopService implements GenericPopupInterface {
+export abstract class VfModulePopupServiceBase {
dynamicInputs: any;
instance: any;
model: any;
@@ -31,16 +30,27 @@ export class VfModulePopuopService implements GenericPopupInterface {
uuidData: Object;
closeDialogEvent: Subject<any> = new Subject<any>();
isUpdateMode: boolean;
+ storeVFModule = (that, formValues: any): void => {
+ formValues.modelInfo = new ModelInfo(that.model);
+ formValues.uuid = formValues.modelInfo.uuid;
+ formValues.isMissingData = false;
+ const vnf = that._store.getState().service.serviceInstance[that.uuidData.serviceId].vnfs[that.uuidData.vnfStoreKey];
+ if (!that.uuidData.vFModuleStoreKey) {
+ this._store.dispatch(createVFModuleInstance(formValues, that.uuidData.modelName, that.uuidData.serviceId, 0, that.uuidData.vnfStoreKey));
+ } else {
+ this._store.dispatch(updateVFModuleInstance(formValues, that.uuidData.modelName, that.uuidData.serviceId, that.uuidData.vFModuleStoreKey, that.uuidData.vnfStoreKey));
+ }
+ };
- constructor(private _basicControlGenerator: BasicControlGenerator,
- private _vfModuleControlGenerator: VfModuleControlGenerator,
- private _iframeService: IframeService,
- private _defaultDataGeneratorService: DefaultDataGeneratorService,
- private _aaiService: AaiService,
- private _basicPopupService : BasicPopupService,
- private _store: NgRedux<AppState>) {
-
+ protected constructor(
+ protected _basicControlGenerator: BasicControlGenerator,
+ protected _vfModuleControlGenerator: VfModuleControlGenerator,
+ protected _iframeService: IframeService,
+ protected _defaultDataGeneratorService: DefaultDataGeneratorService,
+ protected _aaiService: AaiService,
+ protected _basicPopupService: BasicPopupService,
+ protected _store: NgRedux<AppState>) {
}
getInstance(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string): any {
@@ -51,45 +61,6 @@ export class VfModulePopuopService implements GenericPopupInterface {
return vfModules[this.uuidData['modelName']][vfModuleStoreKey];
}
- getDynamicInputs(UUIDData : Object) : FormControlModel[]{
- let dynamic = this._defaultDataGeneratorService.getArbitraryInputs(this._store.getState().service.serviceHierarchy[UUIDData['serviceId']].vfModules[UUIDData['modelName']].inputs);
- return this.getVFModuleDynamicInputs(dynamic, UUIDData);
- }
-
- getVFModuleDynamicInputs(dynamicInputs : any, UUIDData : Object) : FormControlModel[] {
- let result : FormControlModel[] = [];
- if(dynamicInputs) {
- let vfModuleInstance = null;
- if (_.has(this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs, UUIDData['vnfStoreKey']) &&
- _.has(this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs[UUIDData['vnfStoreKey']].vfModules, UUIDData['modelName'])) {
- vfModuleInstance = Object.assign({},this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs[UUIDData['vnfStoreKey']].vfModules[UUIDData['modelName']][UUIDData['vfModuleStoreKey']]);
- }
- result = this._basicControlGenerator.getDynamicInputs(dynamicInputs, vfModuleInstance);
- }
- return result;
- }
-
-
- getGenericFormPopupDetails(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, node: ITreeNode, uuidData: Object, isUpdateMode: boolean): FormPopupDetails {
-
- this.uuidData = uuidData;
- this.instance = this.getInstance(serviceId, vnfStoreKey, vfModuleStoreKey);
- this.getModelInformation(serviceId, uuidData['modelName']);
-
- return new FormPopupDetails(this,
- PopupType.VFMODULE,
- uuidData,
- this.getTitle(isUpdateMode),
- this.getSubLeftTitle(),
- this.getSubRightTitle(),
- this.getControls(serviceId, vnfStoreKey, vfModuleStoreKey, isUpdateMode),
- this.getDynamicInputs(uuidData),
- this.modelInformations,
- (that, form: FormGroup) => {that.onSubmit(that, form);},
- (that: any, form: FormGroup) => {that.onCancel(that, form); }
- );
- }
-
getModelInformation(serviceId: string, modelName: string) {
this._aaiService.getServiceModelById(serviceId).subscribe((result: any) => {
this.serviceModel = new ServiceModel(result);
@@ -116,69 +87,125 @@ export class VfModulePopuopService implements GenericPopupInterface {
});
}
- getControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, isUpdateMode: boolean) {
- if (this._store.getState().service.serviceHierarchy[serviceId].service.vidNotions.instantiationType === 'Macro') {
- return this._vfModuleControlGenerator.getMacroFormControls(serviceId, vnfStoreKey, vfModuleStoreKey, this.uuidData, isUpdateMode);
- } else {
- return this._vfModuleControlGenerator.getAlaCarteFormControls(serviceId, vnfStoreKey, vfModuleStoreKey, this.uuidData, isUpdateMode);
- }
+ protected postSubmitIframeMessage(that) {
+ window.parent.postMessage({
+ eventId: 'submitIframe',
+ data: {
+ serviceModelId: that.serviceModel.uuid
+ }
+ }, "*");
}
+ onCancel(that, form) {
+ form.reset();
+ that._iframeService.removeClassCloseModal('content');
+ this.closeDialogEvent.next(that);
+ }
- onSubmit(that, form: FormGroup) {
- form.value['instanceParams'] = form.value['instanceParams'] && [form.value['instanceParams']];
+ getSubLeftTitle(): string {
+ return this.model.name;
+ }
+
+ getSubRightTitle(): string {
+ return "Module (Heat stack) Instance Details";
+ }
+
+ abstract getTitle(isUpdateMode : boolean) : string;
+ abstract getControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, isUpdateMode: boolean);
+ abstract getDynamicInputs(UUIDData : Object) : FormControlModel[];
+
+ getGenericFormPopupDetails(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, node: ITreeNode, uuidData: Object, isUpdateMode: boolean): FormPopupDetails {
+
+ this.uuidData = uuidData;
+ this.instance = this.getInstance(serviceId, vnfStoreKey, vfModuleStoreKey);
+ this.getModelInformation(serviceId, uuidData['modelName']);
+
+ return new FormPopupDetails(this,
+ PopupType.VFMODULE,
+ uuidData,
+ this.getTitle(isUpdateMode),
+ this.getSubLeftTitle(),
+ this.getSubRightTitle(),
+ this.getControls(serviceId, vnfStoreKey, vfModuleStoreKey, isUpdateMode),
+ this.getDynamicInputs(uuidData),
+ this.modelInformations,
+ (that, form: FormGroup) => {
+ that.onSubmit(that, form);
+ },
+ (that: any, form: FormGroup) => {
+ that.onCancel(that, form);
+ }
+ );
+ }
+
+ updateFormValueWithSupplementaryFile(form: FormGroup, that) {
if (!_.isNil(form.controls['supplementaryFile_hidden_content']) && form.controls['supplementaryFile_hidden_content'].value) {
form.value['supplementaryFileContent'] = JSON.parse(form.controls['supplementaryFile_hidden_content'].value);
if (!_.isNil(form.controls['supplementaryFile_hidden'].value)) {
form.value['supplementaryFileName'] = form.controls['supplementaryFile_hidden'].value.name;
- }
- else {
+ } else {
form.value['supplementaryFileName'] = that.instance.supplementaryFileName;
}
- }
- else {
+ } else {
delete form.value['supplementaryFileContent'];
delete form.value['supplementaryFileName'];
}
- that.storeVFModule(that, form.value);
- window.parent.postMessage({
- eventId: 'submitIframe',
- data: {
- serviceModelId: that.serviceModel.uuid
- }
- }, "*");
- this.onCancel(that, form);
}
+}
+@Injectable()
+export class VfModulePopuopService extends VfModulePopupServiceBase implements GenericPopupInterface {
+
+
+ constructor(_basicControlGenerator: BasicControlGenerator,
+ _vfModuleControlGenerator: VfModuleControlGenerator,
+ _iframeService: IframeService,
+ _defaultDataGeneratorService: DefaultDataGeneratorService,
+ _aaiService: AaiService,
+ _basicPopupService : BasicPopupService,
+ _store: NgRedux<AppState>) {
+ super(_basicControlGenerator, _vfModuleControlGenerator, _iframeService, _defaultDataGeneratorService, _aaiService, _basicPopupService, _store);
- onCancel(that, form) {
- form.reset();
- that._iframeService.removeClassCloseModal('content');
- this.closeDialogEvent.next(that);
}
- storeVFModule = (that, formValues: any): void => {
- formValues.modelInfo = new ModelInfo(that.model);
- formValues.uuid = formValues.modelInfo.uuid;
- formValues.isMissingData = false;
- const vnf = that._store.getState().service.serviceInstance[that.uuidData.serviceId].vnfs[that.uuidData.vnfStoreKey];
+ getDynamicInputs(UUIDData : Object) : FormControlModel[]{
+ let dynamic = this._defaultDataGeneratorService.getArbitraryInputs(this._store.getState().service.serviceHierarchy[UUIDData['serviceId']].vfModules[UUIDData['modelName']].inputs);
+ return this.getVFModuleDynamicInputs(dynamic, UUIDData);
+ }
- if (!that.uuidData.vFModuleStoreKey) {
- this._store.dispatch(createVFModuleInstance(formValues, that.uuidData.modelName, that.uuidData.serviceId, 0, that.uuidData.vnfStoreKey));
- } else {
- this._store.dispatch(updateVFModuleInstance(formValues, that.uuidData.modelName, that.uuidData.serviceId, that.uuidData.vFModuleStoreKey, that.uuidData.vnfStoreKey));
+ getVFModuleDynamicInputs(dynamicInputs : any, UUIDData : Object) : FormControlModel[] {
+ let result : FormControlModel[] = [];
+ if(dynamicInputs) {
+ let vfModuleInstance = null;
+ if (_.has(this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs, UUIDData['vnfStoreKey']) &&
+ _.has(this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs[UUIDData['vnfStoreKey']].vfModules, UUIDData['modelName'])) {
+ vfModuleInstance = Object.assign({},this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs[UUIDData['vnfStoreKey']].vfModules[UUIDData['modelName']][UUIDData['vfModuleStoreKey']]);
+ }
+ result = this._basicControlGenerator.getDynamicInputs(dynamicInputs, vfModuleInstance);
}
- };
+ return result;
+ }
- getTitle(isUpdateMode : boolean) : string {
- return isUpdateMode ? 'Edit Module (Heat stack)' : 'Set new Module (Heat stack)';
+
+ getControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, isUpdateMode: boolean) {
+ if (this._store.getState().service.serviceHierarchy[serviceId].service.vidNotions.instantiationType === 'Macro') {
+ return this._vfModuleControlGenerator.getMacroFormControls(serviceId, vnfStoreKey, vfModuleStoreKey, this.uuidData, isUpdateMode);
+ } else {
+ return this._vfModuleControlGenerator.getAlaCarteFormControls(serviceId, vnfStoreKey, vfModuleStoreKey, this.uuidData, isUpdateMode);
+ }
}
- getSubLeftTitle(): string {
- return this.model.name;
+
+ onSubmit(that, form: FormGroup) {
+ form.value['instanceParams'] = form.value['instanceParams'] && [form.value['instanceParams']];
+ this.updateFormValueWithSupplementaryFile(form, that);
+ that.storeVFModule(that, form.value);
+ this.postSubmitIframeMessage(that);
+ this.onCancel(that, form);
}
- getSubRightTitle(): string {
- return "Module (Heat stack) Instance Details";
+ getTitle(isUpdateMode : boolean) : string {
+ return isUpdateMode ? 'Edit Module (Heat stack)' : 'Set new Module (Heat stack)';
}
+
}
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service.ts
new file mode 100644
index 000000000..bbfe8705e
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service.ts
@@ -0,0 +1,95 @@
+import {Injectable} from "@angular/core";
+import {ITreeNode} from "angular-tree-component/dist/defs/api";
+import {FormGroup} from "@angular/forms";
+import {VfModulePopupServiceBase} from "../vfModule/vfModule.popuop.service";
+import {upgradeVFModule} from "../../../../storeUtil/utils/vfModule/vfModule.actions";
+import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service";
+import {NgRedux} from "@angular-redux/store";
+import {AppState} from "../../../../store/reducers";
+import {BasicControlGenerator} from "../../../genericForm/formControlsServices/basic.control.generator";
+import {VfModuleControlGenerator} from "../../../genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator";
+import {IframeService} from "../../../../utils/iframe.service";
+import {DefaultDataGeneratorService} from "../../../../services/defaultDataServiceGenerator/default.data.generator.service";
+import {AaiService} from "../../../../services/aaiService/aai.service";
+import {BasicPopupService} from "../basic.popup.service";
+import {FormControlModel} from "../../../../models/formControlModels/formControl.model";
+import {CheckboxFormControl} from "../../../../models/formControlModels/checkboxFormControl.model";
+import {FormControlType} from "../../../../models/formControlModels/formControlTypes.enum";
+import {mergeObjectByPathAction} from "../../../../storeUtil/utils/general/general.actions";
+
+export enum UpgradeFormControlNames {
+ RETAIN_VOLUME_GROUPS = 'retainVolumeGroups',
+ RETAIN_ASSIGNMENTS = 'retainAssignments',
+ SDN_C_PRE_LOAD = 'sdncPreLoad',
+}
+
+@Injectable()
+export class VfModuleUpgradePopupService extends VfModulePopupServiceBase {
+ constructor(protected _basicControlGenerator: BasicControlGenerator,
+ protected _vfModuleControlGenerator: VfModuleControlGenerator,
+ protected _iframeService: IframeService,
+ protected _defaultDataGeneratorService: DefaultDataGeneratorService,
+ protected _aaiService: AaiService,
+ protected _basicPopupService: BasicPopupService,
+ protected _store: NgRedux<AppState>,
+ private _sharedTreeService: SharedTreeService) {
+ super(_basicControlGenerator, _vfModuleControlGenerator, _iframeService, _defaultDataGeneratorService, _aaiService, _basicPopupService, _store);
+ }
+
+ node: ITreeNode;
+
+ getDynamicInputs = () => null;
+
+ getControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, isUpdateMode: boolean): FormControlModel[] {
+ let result: FormControlModel[] =[
+ this.getRetainAssignmentsControl(),
+ this.getRetainVolumeGroupsControl(),
+ this._basicControlGenerator.getSDNCControl(null)
+ ];
+
+ const vfModuleInstance = this._vfModuleControlGenerator.getVfModuleInstance(serviceId, vnfStoreKey, this.uuidData, isUpdateMode);
+ result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance);
+ return result;
+ };
+
+ getTitle = (): string => 'Upgrade Module';
+
+ onSubmit(that, form: FormGroup) {
+ const node = that.uuidData.vfModule;
+ const serviceInstanceId: string = that.uuidData.serviceId;
+ const vnfStoreKey = node.parent.data.vnfStoreKey;
+ const modelName = node.data.modelName;
+ const dynamicModelName = node.data.dynamicModelName;
+
+ this.updateFormValueWithSupplementaryFile(form, that);
+
+ this._store.dispatch(upgradeVFModule(modelName, vnfStoreKey, serviceInstanceId, dynamicModelName));
+ this._store.dispatch(mergeObjectByPathAction(['serviceInstance', serviceInstanceId, 'vnfs', vnfStoreKey, 'vfModules', modelName, dynamicModelName], form.value));
+ this._sharedTreeService.upgradeBottomUp(node, serviceInstanceId);
+
+ this.postSubmitIframeMessage(that);
+ this.onCancel(that, form);
+ }
+
+ getRetainVolumeGroupsControl = (): CheckboxFormControl => {
+ return new CheckboxFormControl({
+ type: FormControlType.CHECKBOX,
+ controlName: UpgradeFormControlNames.RETAIN_VOLUME_GROUPS,
+ displayName: 'Retain Volume Groups',
+ dataTestId: UpgradeFormControlNames.RETAIN_VOLUME_GROUPS,
+ value: true,
+ validations: []
+ })
+ };
+
+ getRetainAssignmentsControl = (): CheckboxFormControl => {
+ return new CheckboxFormControl({
+ type: FormControlType.CHECKBOX,
+ controlName: UpgradeFormControlNames.RETAIN_ASSIGNMENTS,
+ displayName: 'Retain Assignments',
+ dataTestId: UpgradeFormControlNames.RETAIN_ASSIGNMENTS,
+ value: true,
+ validations: []
+ })
+ };
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts
new file mode 100644
index 000000000..7c1cc084a
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts
@@ -0,0 +1,201 @@
+import {LogService} from "../../../../utils/log/log.service";
+import {NgRedux} from "@angular-redux/store";
+import {BasicControlGenerator, SDN_C_PRE_LOAD, SUPPLEMENTARY_FILE} from "../../../genericForm/formControlsServices/basic.control.generator";
+import {AaiService} from "../../../../services/aaiService/aai.service";
+import {HttpClient} from "@angular/common/http";
+import {GenericFormService} from "../../../genericForm/generic-form.service";
+import {FormBuilder, FormGroup} from "@angular/forms";
+import {IframeService} from "../../../../utils/iframe.service";
+import {DefaultDataGeneratorService} from "../../../../services/defaultDataServiceGenerator/default.data.generator.service";
+import {BasicPopupService} from "../basic.popup.service";
+import {VfModuleControlGenerator} from "../../../genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator";
+import {SdcUiServices} from "onap-ui-angular";
+import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service";
+import {getTestBed, TestBed} from "@angular/core/testing";
+import {UpgradeFormControlNames, VfModuleUpgradePopupService} from "./vfModule.upgrade.popuop.service";
+import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service";
+import {AppState} from "../../../../store/reducers";
+import {instance, mock} from "ts-mockito";
+import {GeneralActions} from "../../../../storeUtil/utils/general/general.actions";
+import {VfModuleActions} from "../../../../storeUtil/utils/vfModule/vfModule.actions";
+import {ServiceActions} from "../../../../storeUtil/utils/service/service.actions";
+import {FormControlModel} from "../../../../models/formControlModels/formControl.model";
+
+class MockModalService<T> {}
+
+class MockAppStore<T> {}
+
+class MockReduxStore<T> {
+ getState() {
+ return {
+ service: {
+ serviceInstance : {
+ serviceId : {
+ vnfs : {
+ vnfStoreKey : {
+ vfModules: {
+ vfModuleName: {
+ vfModuleId : {
+ supplementaryFileName: "myFileName"
+ }}}}}}}}
+ };
+ }
+
+ dispatch() {}
+}
+
+class MockFeatureFlagsService {}
+
+describe('VFModule popup service', () => {
+ let injector;
+ let service: VfModuleUpgradePopupService;
+ let genericFormService: GenericFormService;
+ let defaultDataGeneratorService: DefaultDataGeneratorService;
+ let fb: FormBuilder;
+ let iframeService: IframeService;
+ let store : NgRedux<AppState>;
+
+ beforeAll(done => (async () => {
+ TestBed.configureTestingModule({
+ providers: [
+ VfModuleUpgradePopupService,
+ BasicControlGenerator,
+ VfModuleControlGenerator,
+ DefaultDataGeneratorService,
+ GenericFormService,
+ FormBuilder,
+ IframeService,
+ AaiService,
+ LogService,
+ BasicPopupService,
+ SharedTreeService,
+ {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
+ {provide: NgRedux, useClass: MockReduxStore},
+ {provide: HttpClient, useClass: MockAppStore},
+ {provide: SdcUiServices.ModalService, useClass: MockModalService}
+ ]
+ });
+ await TestBed.compileComponents();
+
+ injector = getTestBed();
+ service = injector.get(VfModuleUpgradePopupService);
+ genericFormService = injector.get(GenericFormService);
+ defaultDataGeneratorService = injector.get(DefaultDataGeneratorService);
+ fb = injector.get(FormBuilder);
+ iframeService = injector.get(IframeService);
+ store = injector.get(NgRedux);
+ service.uuidData = {
+ modelName: 'vfModuleName',
+ vFModuleStoreKey: 'vfModuleId'
+ };
+
+ })().then(done).catch(done.fail));
+
+ test('getTitle should return the correct title', () => {
+ expect(service.getTitle()).toBe("Upgrade Module")
+ });
+
+ function findControlByName(controls: FormControlModel[], controlName: string) : FormControlModel {
+ return controls.find((control) => {
+ return control.controlName === controlName;
+ });
+ }
+
+ function getControlByNameAndCheckValue(controlName: string, expectedValue: any) {
+ const controls = service.getControls('serviceId', 'vnfStoreKey', 'vfModuleId', true);
+ const control = findControlByName(controls, controlName);
+ expect(control).toBeDefined();
+ expect(control.value).toEqual(expectedValue);
+ }
+
+ test('get controls should return retainAssignments control with true value', ()=> {
+ getControlByNameAndCheckValue(UpgradeFormControlNames.RETAIN_ASSIGNMENTS, true);
+ });
+
+ test('get controls should return retainVolumeGroup control with true value', ()=> {
+ getControlByNameAndCheckValue(UpgradeFormControlNames.RETAIN_VOLUME_GROUPS, true);
+ });
+
+ test('get controls should contain SUPPLEMENTARY_FILE controller', ()=> {
+
+ //when
+ const controls = service.getControls('serviceId', 'vnfStoreKey', 'vfModuleId', true);
+
+ //then
+ const control = findControlByName(controls, SUPPLEMENTARY_FILE);
+ expect(control).toBeDefined();
+ expect(control.selectedFile).toBe("myFileName");
+ });
+
+ test('on submit should call merge action of form value to vfModule', () => {
+
+ //given
+
+ const serviceId = "serviceId5";
+ const vnfStoreKey = 'vnfStoreKey3';
+ const modelName = 'modelA';
+ const dynamicModelName = 'dynamicModel';
+ const that = {
+ uuidData : {
+ vfModule : {
+ data : {
+ modelName,
+ dynamicModelName
+ },
+ parent : {
+ data: {
+ vnfStoreKey
+ }}},
+ serviceId
+ },
+ serviceModel: {
+ uuid : "someUuid"
+ },
+ _iframeService: {
+ removeClassCloseModal : jest.fn()
+ }
+ };
+
+ let mockFrom: FormGroup = mock(FormGroup);
+ let form = instance(mockFrom);
+ form.value = {
+ a: "value",
+ b: "another"
+ };
+ form.controls = {
+ supplementaryFile_hidden_content : {
+ value: '{"c": "c", "d": 1}'
+ },
+ supplementaryFile_hidden : {
+ value: {
+ name: "name"
+ }
+ }
+ };
+
+ let expectedMergePayload = {
+ a: "value",
+ b: "another",
+ supplementaryFileContent: {c: "c", d: 1},
+ supplementaryFileName: "name"
+ };
+
+ spyOn(store, 'dispatch');
+
+ //when
+ service.onSubmit(that, form);
+
+ //then
+ expect(store.dispatch).toBeCalledWith(
+ {type: GeneralActions.MERGE_OBJECT_BY_PATH, path: ['serviceInstance', serviceId, 'vnfs', vnfStoreKey, 'vfModules',modelName, dynamicModelName], payload:expectedMergePayload});
+ expect(store.dispatch).toBeCalledWith(
+ {type: VfModuleActions.UPGRADE_VFMODULE, dynamicModelName: "dynamicModel", modelName: "modelA", serviceId: "serviceId5", vnfStoreKey: "vnfStoreKey3"});
+ expect(store.dispatch).toBeCalledWith({type: ServiceActions.UPGRADE_SERVICE_ACTION, serviceUuid: "serviceId5"});
+
+ });
+
+
+ test( 'get controls should return usePreload with false value', () => {
+ getControlByNameAndCheckValue(SDN_C_PRE_LOAD, false);
+ });
+});
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.spec.ts
index 6458e4f97..c4317f241 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.spec.ts
@@ -14,6 +14,7 @@ import {VnfControlGenerator} from "../../../genericForm/formControlsServices/vnf
import {UUIDData} from "../../generic-form-popup.component";
import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service";
import {getTestBed, TestBed} from "@angular/core/testing";
+import {VfModuleUpgradePopupService} from "../vfModuleUpgrade/vfModule.upgrade.popuop.service";
class MockAppStore<T> {}
@@ -29,10 +30,7 @@ class MockReduxStore<T> {
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
"FLAG_ADVANCED_PORTS_FILTER": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
"FLAG_REGION_ID_FROM_REMOTE": true,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
@@ -2261,6 +2259,7 @@ describe('vnf new popup service', () => {
LogService,
BasicPopupService,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
BasicControlGenerator,
VnfControlGenerator,
{provide: NgRedux, useClass: MockReduxStore},
@@ -2335,6 +2334,10 @@ describe('vnf new popup service', () => {
expect(service.modelInformations[13].values).toEqual(['5']);
});
+ test('when there is no max instances in model , shell return maximum item with Unlimited text', () =>{
+ expect(service.createMaximumToInstantiateModelInformationItem({}).values[0]).toEqual('Unlimited (default)');
+ });
+
test('getSubLeftTitle new vnf popup should return service model name', () => {
service.uuidData = {
serviceId: '6e59c5de-f052-46fa-aa7e-2fca9d674c44',
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.ts
index b23f74530..283603275 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.ts
@@ -97,11 +97,21 @@ export class VnfPopupService implements GenericPopupInterface{
new ModelInformationItem("Service type", "serviceType", [this.serviceModel.serviceType]),
new ModelInformationItem("Service role", "serviceRole", [this.serviceModel.serviceRole]),
new ModelInformationItem("Minimum to instantiate", "vnf-min", [!_.isNil(this.model.min) ? this.model.min.toString() : '0'], "", false),
- new ModelInformationItem("Maximum to instantiate", "vnf-max", [!_.isNil(this.model.max) ? this.model.max.toString() : '1'], "", false)
+ (this.createMaximumToInstantiateModelInformationItem(this.model))
];
})
}
+ createMaximumToInstantiateModelInformationItem(model) {
+ return new ModelInformationItem(
+ "Maximum to instantiate",
+ "vnf-max",
+ [!_.isNil(model.max) ? model.max.toString() : Constants.ModelInfo.UNLIMITED_DEFAULT],
+ "",
+ false
+ );
+ }
+
getSubLeftTitle(): string {
return "VNF MODEL: " + this._store.getState().service.serviceHierarchy[this.uuidData['serviceId']].vnfs[this.uuidData['modelName']].name;
}
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service.spec.ts
index 5397a7233..3a81e5b2b 100644
--- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service.spec.ts
@@ -14,6 +14,7 @@ import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flag
import {VnfGroupPopupService} from "./vnfGroup.popup.service";
import {VnfGroupControlGenerator} from "../../../genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator";
import {getTestBed, TestBed} from "@angular/core/testing";
+import {VfModuleUpgradePopupService} from "../vfModuleUpgrade/vfModule.upgrade.popuop.service";
class MockAppStore<T> {}
@@ -29,10 +30,7 @@ class MockReduxStore<T> {
"FLAG_SHOW_VERIFY_SERVICE": false,
"FLAG_SERVICE_MODEL_CACHE": true,
"FLAG_ADVANCED_PORTS_FILTER": true,
- "CREATE_INSTANCE_TEST": false,
- "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false,
"FLAG_REGION_ID_FROM_REMOTE": true,
- "EMPTY_DRAWING_BOARD_TEST": false,
"FLAG_ADD_MSO_TESTAPI_FIELD": true
},
"type": "[FLAGS] Update"
@@ -2258,6 +2256,7 @@ describe('vnf group new popup service', () => {
LogService,
BasicPopupService,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
BasicControlGenerator,
VnfGroupControlGenerator,
{provide: NgRedux, useClass: MockReduxStore},
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html
new file mode 100644
index 000000000..19f641a56
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html
@@ -0,0 +1,164 @@
+<div id="template-popup" class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button"
+ class="close"
+ (click)="closeModal()">&times;
+ </button>
+ <span [attr.data-tests-id]="'template-modal-title'"
+ class="modal-title">Templates
+ </span>
+ </div>
+ <div class="modal-body templateModalBody">
+ <div class="row description-section">
+ <div class="col-md-6">
+ <div [attr.data-tests-id]="'description-part-1'">The following list presents previous instantiations done for
+ this model in this version.
+ </div>
+ <div [attr.data-tests-id]="'description-part-2'">You may use one of them as a baseline for your instantiation
+ or start from scratch.
+ </div>
+ <div [attr.data-tests-id]="'description-part-3'">Once you selecting one allows you to change the data before
+ start instantiating.
+ </div>
+ </div>
+ <div class="col-md-6">
+ <div class="col-md-6">
+ </div>
+ <div class="col-md-6">
+ <input
+ class="filter-input form-control input-text"
+ placeholder="Filter..."
+ [(ngModel)]="filterText">
+ </div>
+ </div>
+ </div>
+ <div class="row" style="margin-left: 0;margin-right: 0;padding: 20px;">
+ <table id="member-table" class="table table-bordered" style="table-layout: fixed">
+ <thead class="thead-dark">
+ <tr>
+ <th class="header-title" id="header-userId">User ID</th>
+ <th class="header-title" id="header-createDate" style="width: 21ch;">Date</th>
+ <th class="header-title" id="header-instanceName" style="max-width: 50ch;">Instance Name</th>
+ <th class="header-title" id="header-instantiationStatus" style="width: 30ch;">Instantiation Status</th>
+ <th class="header-title" id="header-summary">Summary</th>
+ <th class="header-title" id="header-region">Region</th>
+ <th class="header-title" id="header-tenant">Tenant</th>
+ <th class="header-title" id="header-aicZone">AIC Zone</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="member-table-row"
+ *ngFor="let item of filterTableData | searchFilter: filterText ;"
+ (click)="selectedJobId = item.jobId"
+ [ngClass]="{'selected' : selectedJobId === item.jobId}"
+ [attr.data-tests-id]="'row-' + item.jobId">
+ <td>
+ <div>
+ <custom-ellipsis
+ [dataTestId]="'userId-' + item.jobId"
+ [id]="item.userId"
+ [value]="item.userId"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td style="width: 21ch;">
+ <div>
+ <custom-ellipsis
+ [dataTestId]="'createDate-' + item.jobId"
+ [id]="item.createDate"
+ [value]="item.createDate"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td style="max-width: 50ch;">
+ <div>
+ <custom-ellipsis
+ [showDots]="true"
+ [dataTestId]="'instanceName-' + item.jobId"
+ [id]="item.instanceName"
+ [value]="item.instanceName"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td>
+ <div>
+ <custom-ellipsis
+ [showDots]="true"
+ [dataTestId]="'instantiationStatus-' + item.jobId"
+ [id]="item.instantiationStatus"
+ [value]="item.instantiationStatus"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td>
+ <div>
+ <custom-ellipsis
+ [dataTestId]="'summary-' + item.jobId"
+ [id]="item.summary"
+ [value]="item.summary"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td>
+ <div>
+ <custom-ellipsis
+ [showDots]="true"
+ [dataTestId]="'region-' + item.jobId"
+ [id]="item.region"
+ [value]="item.region"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td>
+ <div>
+ <custom-ellipsis
+ [showDots]="true"
+ [dataTestId]="'tenant-' + item.jobId"
+ [id]="item.tenant"
+ [value]="item.tenant"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ <td>
+ <div>
+ <custom-ellipsis
+ [dataTestId]="'aicZone-' + item.jobId"
+ [id]="item.aicZone"
+ [value]="item.aicZone"
+ [breakWord]="true">
+ </custom-ellipsis>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ </div>
+ <div class="modal-footer row" style="padding: 0">
+ <div class="col-md-6">
+ </div>
+ <div class="col-md-6" style="padding: 15px;padding-right: 35px;">
+ <button
+ [disabled]="selectedJobId === null"
+ [attr.data-tests-id]="'LoadTemplateButton'"
+ type="button" class="btn btn-primary submit"
+ (click)="loadTemplate()"><span>Load Template</span>
+ </button>
+ <button
+ [attr.data-tests-id]="'startFromScratchButton'"
+ type="button" class="btn btn-success submit startFromScratchButton"
+ (click)="closeModal()"><span>Start from Scratch</span>
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss
new file mode 100644
index 000000000..267d2cee0
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss
@@ -0,0 +1,196 @@
+$grid-border: 1px #d2d2d2 solid;
+
+#template-popup {
+ color: #191919;
+
+ thead {
+ background: #F8F8F8;
+ }
+ .left-panel {
+ background: #f2f2f2;
+ border-right: $grid-border;
+ }
+
+ .header-common {
+ height: 100%;
+ align-items: center;
+ display: flex;
+ font-family: OpenSans-Semibold;
+ font-size: 12px;
+ }
+
+ .header-text {
+ padding-left: 30px;
+ @extend .header-common;
+ }
+
+ .header-left {
+ grid-area: header-left;
+ @extend .header-text;
+ @extend .left-panel;
+ border-bottom: $grid-border;
+
+ span {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ }
+ ;
+ }
+
+ .header-right {
+ grid-area: header-right;
+
+ @extend .header-text;
+ }
+
+ .quantity-label {
+ grid-area: quantity-label;
+ @extend .header-common;
+ height: 100%;
+ font-family: OpenSans-Regular;
+ }
+
+ input[type="number"]:hover::-webkit-inner-spin-button {
+ height: 20px;
+ }
+
+ .popup-content {
+ display: grid;
+ grid-template-columns: 400px auto 30px 93px;
+ grid-template-rows: 50px calc(100vh - 180px);
+ grid-template-areas: "header-left header-right quantity-label quantity" "model-information instance-form instance-form instance-form";
+ padding: 0;
+ }
+}
+
+.modal {
+ background-color: #191919;
+ opacity: 0.8;
+}
+
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0;
+}
+
+@media (min-width: 1150px) {
+ .popup-content {
+ grid-template-rows: 30px 680px;
+ }
+}
+
+.modal-content {
+ border-radius: 0;
+ box-shadow: none;
+ border: none;
+ min-height: calc(100vh);
+
+}
+
+.modal-footer {
+ padding: 0;
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+
+ .cancel {
+ width: 120px;
+ height: 36px;
+ background: #ffffff;
+ border: 1px solid #009fdb;
+ border-radius: 2px;
+
+ span {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ color: #009fdb;
+ line-height: 16px;
+ }
+ }
+
+ .startFromScratchButton {
+ width: 150px !important;
+ }
+
+ .submit {
+ min-width: 120px;
+ height: 36px;
+ background: #009fdb;
+ border-radius: 2px;
+ border-color: #009fdb;
+
+
+ span {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ color: #FFFFFF;
+ line-height: 16px;
+ }
+ }
+}
+
+.modal-header {
+ background-color: #009fdb;
+
+ padding-bottom: 13px;
+ padding-top: 13px;
+ padding-left: 29px;
+ padding-right: 21px;
+
+ .close {
+ font-size: 32px;
+ font-weight: 200;
+ color: #d8d8d8;
+ text-shadow: none;
+ filter: none;
+ opacity: 1;
+ }
+
+ .modal-title {
+ font-family: OpenSans-Regular;
+ font-size: 24px;
+ color: #fff;
+ line-height: 34px;
+ }
+}
+
+.modal-body {
+ padding: 0;
+ height: calc(85vh);
+
+ .description-section {
+ padding: 20px;
+ font-size: 20px;
+ }
+
+ .filter-input {
+ float: right;
+ width: 50%;
+ }
+
+ .details-item {
+ text-align: right;
+ }
+
+
+ td.loadTemplateButton {
+ text-align: center;
+ vertical-align: middle;
+ }
+
+ td {
+ text-align: center;
+ vertical-align: middle;
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+
+ .member-table-row:hover {
+ background: #80808033 !important;
+ }
+
+ .member-table-row.selected {
+ background: #8080808f !important;
+ }
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts
new file mode 100644
index 000000000..4d89750f9
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts
@@ -0,0 +1,57 @@
+import {Component, OnDestroy, OnInit} from "@angular/core";
+import {DialogComponent, DialogService} from "ng2-bootstrap-modal";
+import {IframeService} from "../../../utils/iframe.service";
+import {ActivatedRoute} from "@angular/router";
+import {ServiceInfoService} from "../../../server/serviceInfo/serviceInfo.service";
+import {InstantiationTemplatesModalService} from "./instantiation.templates.modal.service";
+import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.model";
+
+@Component({
+ selector: 'template-modal',
+ templateUrl: 'instantiation.templates.modal.component.html',
+ styleUrls: ['instantiation.templates.modal.component.scss']
+})
+
+export class InstantiationTemplatesModalComponent extends DialogComponent<string, boolean> implements OnInit, OnDestroy {
+
+ selectedJobId : string = null;
+ templateModalComponentService: InstantiationTemplatesModalService;
+ originalTableData: InstantiationTemplatesRowModel[] = [];
+ filterTableData : InstantiationTemplatesRowModel[] = [];
+ filterText: string;
+
+ constructor(dialogService: DialogService,
+ private _iframeService: IframeService,
+ private _serviceInfoService: ServiceInfoService,
+ private _templateModalComponentService: InstantiationTemplatesModalService,
+ private _route: ActivatedRoute) {
+ super(dialogService);
+ this.templateModalComponentService = _templateModalComponentService;
+ }
+
+ ngOnInit(): void {
+ this.filterText = '';
+ this._route
+ .queryParams
+ .subscribe(params => {
+ this._serviceInfoService.getServicesJobInfo(true, params['serviceModelId']).subscribe((jobs) => {
+ this.originalTableData = this._templateModalComponentService.convertResponseToUI(jobs);
+ this.filterTableData = this.originalTableData;
+ });
+ });
+ }
+
+ loadTemplate = () => {
+
+ };
+
+
+ closeModal(): void {
+ this._iframeService.removeClassCloseModal('content');
+ this.dialogService.removeDialog(this);
+ setTimeout(() => {
+ window.parent.postMessage("closeIframe", "*");
+ }, 15);
+
+ }
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts
new file mode 100644
index 000000000..1ff0f61e2
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts
@@ -0,0 +1,133 @@
+import {getTestBed, TestBed} from '@angular/core/testing';
+import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
+import {InstantiationTemplatesModalService} from "./instantiation.templates.modal.service";
+import {AaiService} from "../../../services/aaiService/aai.service";
+import {ActivatedRoute} from "@angular/router";
+import {IframeService} from "../../../utils/iframe.service";
+import {NgRedux} from "@angular-redux/store";
+import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.service";
+import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.model";
+
+
+class ActivatedRouteMock<T> {
+ queryParams() {
+ return {
+ serviceModelId: '6e59c5de-f052-46fa-aa7e-2fca9d674c44'
+ }
+ }
+}
+
+class MockAppStore {
+
+}
+
+describe('instantiation templates modal service', () => {
+ let injector;
+ let service: InstantiationTemplatesModalService;
+ let httpMock: HttpTestingController;
+ let _aaiService: AaiService;
+ let _activatedRoute: ActivatedRoute;
+
+ beforeAll(done => (async () => {
+ TestBed.configureTestingModule({
+ imports: [HttpClientTestingModule],
+ providers: [InstantiationTemplatesModalService,
+ IframeService,
+ AaiService,
+ FeatureFlagsService,
+ {provide: ActivatedRoute, useClass: ActivatedRouteMock},
+ {provide: NgRedux, useClass: MockAppStore}
+ ]
+ });
+ await TestBed.compileComponents();
+
+ injector = getTestBed();
+ service = injector.get(InstantiationTemplatesModalService);
+ httpMock = injector.get(HttpTestingController);
+ _aaiService = injector.get(AaiService);
+ _activatedRoute = injector.get(ActivatedRoute);
+
+ })().then(done).catch(done.fail));
+
+
+ test('service should be defined', () => {
+ expect(service).toBeDefined();
+ });
+
+
+ test('convertResponseToUI - should return table data', () => {
+ const jobs = [{
+ "id": 5,
+ "created": 1524995555000,
+ "modified": 1524995556000,
+ "action": "INSTANTIATE",
+ "createdId": null,
+ "modifiedId": null,
+ "rowNum": null,
+ "auditUserId": null,
+ "auditTrail": null,
+ "jobId": "9f88fdb5-bb47-4bf3-8c5f-98f1ad0ec87c",
+ "templateId": "ce4ec177-cfc8-483e-8a2c-b7aea53fd740",
+ "userId": "16807000",
+ "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d91",
+ "requestId": null,
+ "jobStatus": "FAILED",
+ "statusModifiedDate": 1524995555000,
+ "hidden": false,
+ "pause": false,
+ "owningEntityId": "aaa1",
+ "owningEntityName": "aaa1",
+ "project": "WATKINS",
+ "aicZoneId": "BAN1",
+ "aicZoneName": "VSDKYUTP-BAN1",
+ "tenantId": "1178612d2b394be4834ad77f567c0af2",
+ "tenantName": "AIN Web Tool-15-D-SSPtestcustome",
+ "regionId": "hvf6",
+ "regionName": null,
+ "serviceType": "TYLER SILVIA",
+ "subscriberName": "e433710f-9217-458d-a79d-1c7aff376d89",
+ "serviceInstanceId": null,
+ "serviceInstanceName": 'serviceInstanceName',
+ "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
+ "serviceModelName": "ComplexService",
+ "serviceModelVersion": "1.0",
+ "createdBulkDate": 1524995555000,
+ "isRetryEnabled": false
+ }];
+ const tableRows: InstantiationTemplatesRowModel[] = service.convertResponseToUI(jobs);
+ expect(tableRows).toHaveLength(1);
+ expect(tableRows[0].userId).toEqual('16807000');
+ expect((new Date(tableRows[0].createDate)).toISOString()).toEqual('2018-04-29T09:52:35.000Z');
+ expect(tableRows[0].instanceName).toEqual('serviceInstanceName');
+ expect(tableRows[0].instantiationStatus).toEqual('FAILED');
+ expect(tableRows[0].region).toEqual('hvf6 (AAA1)');
+ expect(tableRows[0].tenant).toEqual('AIN Web Tool-15-D-SSPtestcustome');
+ expect(tableRows[0].aicZone).toEqual('VSDKYUTP-BAN1');
+ expect(tableRows[0].jobId).toEqual('9f88fdb5-bb47-4bf3-8c5f-98f1ad0ec87c');
+ });
+
+
+ test('getCloudOwner should remove "-att" from owningEntityName : "att-owner', () => {
+ let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({
+ owningEntityName: 'att-owner',
+ regionId: 'regionId'
+ });
+ expect(result.region).toEqual('regionId (OWNER)');
+ });
+
+ test('getCloudOwner should not return owningEntityName if not exist', () => {
+ let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({owningEntityName: null, regionId: 'regionId'});
+ expect(result.region).toEqual('regionId');
+ });
+
+ test('getInstanceName should return instance name id exist if not exist', () => {
+ let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({serviceInstanceName: 'instanceName'});
+ expect(result.instanceName).toEqual('instanceName');
+ });
+
+ test('getInstanceName should return <Automatically generated> if instance name not exist', () => {
+ let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({});
+ expect(result.instanceName).toEqual('<Automatically generated>');
+ });
+
+});
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts
new file mode 100644
index 000000000..7126da36a
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts
@@ -0,0 +1,15 @@
+import {Injectable} from "@angular/core";
+import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.model";
+
+@Injectable()
+export class InstantiationTemplatesModalService {
+ convertResponseToUI = (jobsResponse: any[]): InstantiationTemplatesRowModel[] => {
+ let tableRows: InstantiationTemplatesRowModel[] = [];
+
+ jobsResponse.forEach((job) => {
+ tableRows.push(new InstantiationTemplatesRowModel(job));
+ });
+
+ return tableRows;
+ };
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts
new file mode 100644
index 000000000..08982cc67
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts
@@ -0,0 +1,51 @@
+import * as moment from 'moment';
+import * as _ from 'lodash';
+
+export class InstantiationTemplatesRowModel {
+ readonly jobId: string;
+ readonly userId ?: string;
+ readonly createDate ?: string;
+ readonly instanceName ?: string;
+ readonly instantiationStatus?: string;
+ readonly summary?: string;
+ readonly region?: string;
+ readonly tenant?: string;
+ readonly aicZone?: string;
+
+ constructor(data) {
+ this.jobId = data.jobId;
+ this.userId = !_.isNil(data.created) ? data.userId : null;
+ this.createDate = !_.isNil(data.created) ? moment(data.created).format("YYYY-MM-DD HH:mm:ss") : null;
+ this.instanceName = this.getInstanceName(data.serviceInstanceName);
+ this.instantiationStatus = !_.isNil(data.jobStatus) ? data.jobStatus : null;
+ this.summary = null;
+ this.region = this.getRegion(data.regionId, data.owningEntityName);
+ this.tenant = !_.isNil(data.tenantName) ? data.tenantName : null;
+ this.aicZone = !_.isNil(data.aicZoneName) ? data.aicZoneName : null;
+
+ }
+
+
+ /**************************************************************************************************
+ return the LCP region and in brackets the cloud owner removing the “att-“ with capital letters.
+ **************************************************************************************************/
+ getCloudOwner = (owningEntityName: string): string => {
+ const splitByAtt: string[] = owningEntityName.split('att-');
+ let owning: string = splitByAtt[splitByAtt.length - 1];
+ return owning.toUpperCase();
+ };
+
+ getRegion = (regionId: string, owningEntityName: string): string => {
+ const convertOwning = !_.isNil(owningEntityName) ? `(${this.getCloudOwner(owningEntityName)})` : '';
+ return `${regionId} ${convertOwning}`.trim();
+ };
+
+
+ getInstanceName = (instanceName?: string): string => {
+ if (_.isNil(instanceName)) {
+ return '<Automatically generated>';
+ }
+ return instanceName;
+ }
+}
+
diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts
index 8ea3d2d0b..40d74d63f 100644
--- a/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts
+++ b/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts
@@ -14,6 +14,8 @@ export class FormPopupDetails {
modelInformationItems: ModelInformationItem[];
onSubmit : (that : any, form: FormGroup , ...args) => void;
onCancel : (that : any, form: FormGroup) => void;
+ onOtherAction: (that: any, form: FormGroup) => void;
+
constructor(that : any,
popupTypeName : PopupType ,
@@ -25,7 +27,8 @@ export class FormPopupDetails {
dynamicInputsControlList : FormControlModel[],
modelInformationItems : ModelInformationItem[],
onSubmit : (that : any, form : FormGroup, ...args) => void,
- onCancel : (that : any, form : FormGroup) => void){
+ onCancel: (that: any, form: FormGroup) => void,
+ onOtherAction?: (that: any, form: FormGroup) => void) {
this.title = title;
this.leftSubTitle = leftSubTitle;
this.rightSubTitle = rightSubTitle;
@@ -34,6 +37,7 @@ export class FormPopupDetails {
this.modelInformationItems = modelInformationItems;
this.onSubmit = onSubmit;
this.onCancel = onCancel;
+ this.onOtherAction = onOtherAction;
this.popupTypeName = popupTypeName;
this.UUIDData = UUIDData;
this.that = that;
@@ -49,6 +53,7 @@ export enum PopupType {
VNF_MACRO ='vnf macro',
VNF_A_LA_CARTE = 'vnf a-la-carte',
VFMODULE = 'vfModule',
+ VFMODULE_UPGRADE = 'vfModule_upgrade',
NETWORK_MACRO = 'network_macro',
VNF_GROUP = 'vnfGroup'
}
diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts
index b13745104..f5db715ba 100644
--- a/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts
+++ b/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts
@@ -7,10 +7,14 @@ export class MultiselectFormControl extends FormControlModel{
options$ : Observable<any[]>;
args : string[];
onInit: (data : MultiselectFormControl, form: FormGroup) => Observable<any>;
- selectedItems : string;
+ selectedItems : any[];
onInitSelectedItems : string[];
+ selectedFieldName : string;
ngValue : string;
settings: {};
+ onInitSelectedField?: string[];
+ convertOriginalDataToArray? : (values)=> void;
+ limitSelection?: number;
constructor(data) {
@@ -18,10 +22,14 @@ export class MultiselectFormControl extends FormControlModel{
this.type = FormControlType.MULTI_SELECT;
this.options$ = data.options;
this.onInit = data.onInit;
- this.selectedItems = data.selectedItems;
+ this.selectedItems = data.selectedItems || [];
this.onInitSelectedItems = data.onInitSelectedItems ? data.onInitSelectedItems : null;
this.ngValue = data.selectedField ? data.selectedField : 'id';
+ this.selectedFieldName = data.selectedFieldName;
this.settings = data.settings || {};
+ this.onInitSelectedField = data.onInitSelectedField ? data.onInitSelectedField : null;
+ this.convertOriginalDataToArray = data.convertOriginalDataToArray ? data.convertOriginalDataToArray : null
+ this.limitSelection = data.limitSelection ? data.limitSelection : 1000;
}
}
diff --git a/vid-webpack-master/src/app/shared/models/networkModel.ts b/vid-webpack-master/src/app/shared/models/networkModel.ts
index 03f118eb7..b4879a59d 100644
--- a/vid-webpack-master/src/app/shared/models/networkModel.ts
+++ b/vid-webpack-master/src/app/shared/models/networkModel.ts
@@ -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);
}
}
diff --git a/vid-webpack-master/src/app/shared/models/vfModule.ts b/vid-webpack-master/src/app/shared/models/vfModule.ts
index c75202124..8f92ba428 100644
--- a/vid-webpack-master/src/app/shared/models/vfModule.ts
+++ b/vid-webpack-master/src/app/shared/models/vfModule.ts
@@ -1,4 +1,5 @@
import {NodeModel, NodeModelResponseInterface} from "./nodeModel";
+import {Utils} from "../utils/utils";
export interface Properties{
@@ -23,7 +24,7 @@ export class VfModule extends NodeModel {
modelCustomizationName: string;
volumeGroupAllowed : boolean;
- constructor(vf?: VFModuleResponseInterface) {
+ constructor(vf?: VFModuleResponseInterface, flags?: { [key: string]: boolean }) {
super(vf);
if(vf){
this.customizationUuid = vf.customizationUuid;
@@ -32,7 +33,7 @@ export class VfModule extends NodeModel {
}
if (vf && vf.properties) {
this.min = vf.properties.minCountInstances;
- this.max = vf.properties.maxCountInstances;
+ this.max = Utils.getMaxVfModule(vf.properties, flags);
this.initial = vf.properties.initialCount;
this.rollbackOnFailure = true
}
diff --git a/vid-webpack-master/src/app/shared/models/vnfModel.ts b/vid-webpack-master/src/app/shared/models/vnfModel.ts
index 8389606b6..220dc0fc5 100644
--- a/vid-webpack-master/src/app/shared/models/vnfModel.ts
+++ b/vid-webpack-master/src/app/shared/models/vnfModel.ts
@@ -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);
}
}
-
}
diff --git a/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts
new file mode 100644
index 000000000..2567cbf27
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts
@@ -0,0 +1,17 @@
+import {SearchFilterPipe} from "./search-filter.pipe";
+import * as _ from 'lodash';
+
+describe('Search filter pipe', () => {
+
+ const items= [{'id':1, 'name': 'aaa'},
+ {'id':12, 'name': 'bbb', 'children':{'first': 155, 'second': 2, 'third': 3}},
+ {'id':3, 'name': 'ccc', 'children':{'first': 1, 'BbB': 'BbB', 'third': 3}},
+ {'id':4, 'name': 'aad', 'children':{'first': 1, 'second': 2, 'third': 3}}];
+
+ test('should return items contains substring bb', () => {
+ let filter = new SearchFilterPipe();
+ let res:any[] = filter.transform(items,'bb');
+ expect(_.map(res, 'name' )).toEqual(['bbb','ccc']);
+ });
+
+});
diff --git a/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts
new file mode 100644
index 000000000..6e5cfc667
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts
@@ -0,0 +1,43 @@
+import {Pipe, PipeTransform} from '@angular/core';
+import * as _ from 'lodash';
+
+@Pipe({
+ name: 'searchFilter'
+})
+export class SearchFilterPipe implements PipeTransform {
+ transform(items: Object[], searchText: string): any[] {
+ if (!items) return [];
+ if (!searchText) return items;
+ return items.filter((item: object) => {
+
+ const deepFlatObject = this.flatten(item);
+
+ const values = _.values(deepFlatObject).map((item: string) => {
+ return item.toString().toLowerCase()
+ });
+
+ return _.some(values, _.method('includes', searchText.toLowerCase()));
+ });
+ }
+
+ flatten = object => {
+ return Object.assign(
+ {},
+ ...(function _flatten(objectBit, path = '') {
+ //spread the result into our return object
+ if(objectBit === null) return [];
+ return [].concat(
+ //concat everything into one level
+
+ ...Object.keys(objectBit).map(
+ //iterate over object
+ key =>
+ typeof objectBit[key] === 'object' //check if there is a nested object
+ ? _flatten(objectBit[key], `${path}/${key}`) //call itself if there is
+ : { [`${path}/${key}`]: objectBit[key] } //append object with it’s path as key
+ )
+ );
+ })(object)
+ );
+ };
+}
diff --git a/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.spec.ts b/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.spec.ts
new file mode 100644
index 000000000..1a3a1ab3f
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.spec.ts
@@ -0,0 +1,66 @@
+import {RecreateResolver} from "./recreate.resolver";
+import {getTestBed, TestBed} from '@angular/core/testing';
+import {NgRedux} from "@angular-redux/store";
+import {InstantiationTemplatesService} from "../../services/templateService/instantiationTemplates.service";
+import {AaiService} from "../../services/aaiService/aai.service";
+import {mock} from "ts-mockito";
+import {ServiceInstance} from "../../models/serviceInstance";
+import {HttpClientTestingModule} from "@angular/common/http/testing";
+import {FeatureFlagsService} from "../../services/featureFlag/feature-flags.service";
+import {convertToParamMap} from "@angular/router";
+import {of} from 'rxjs/observable/of'
+
+class MockAppStore<T> {
+ getState() {}
+}
+
+describe('Recreate resolver', () => {
+
+ let injector;
+ let recreateResolver: RecreateResolver;
+ let aaiService: AaiService;
+ let instantiationTemplatesService: InstantiationTemplatesService;
+
+ beforeAll(done => (async () => {
+ TestBed.configureTestingModule({
+ imports: [HttpClientTestingModule],
+ providers: [
+ FeatureFlagsService,
+ InstantiationTemplatesService,
+ RecreateResolver,
+ AaiService,
+ {provide: NgRedux, useClass: MockAppStore},
+ ]
+ });
+ await TestBed.compileComponents();
+
+ injector = getTestBed();
+ recreateResolver = injector.get(RecreateResolver);
+ aaiService = injector.get(AaiService);
+ instantiationTemplatesService = injector.get(InstantiationTemplatesService);
+ })().then(done).catch(done.fail));
+
+ test("when resolve() invoked -> then getServiceModelById and retrieveAndStoreInstantiationTemplateTopology are called", done => {
+ jest.spyOn(aaiService, 'getServiceModelById')
+ .mockReturnValue(of({}));
+ jest.spyOn(instantiationTemplatesService, 'retrieveAndStoreInstantiationTemplateTopology')
+ .mockReturnValue(of(mock(ServiceInstance)));
+
+ recreateResolver.resolve(<any>{
+ queryParamMap:
+ convertToParamMap({
+ serviceModelId: "someServiceModelId",
+ jobId: "someJobId",
+ })
+ })
+
+ .subscribe(() => {
+ expect(aaiService.getServiceModelById)
+ .toHaveBeenCalledWith("someServiceModelId");
+ expect(instantiationTemplatesService.retrieveAndStoreInstantiationTemplateTopology)
+ .toHaveBeenCalledWith("someJobId", "someServiceModelId");
+ done();
+ });
+ })
+
+});
diff --git a/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.ts b/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.ts
new file mode 100644
index 000000000..b7e952a64
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.ts
@@ -0,0 +1,29 @@
+import {Injectable} from "@angular/core";
+import {NgRedux} from "@angular-redux/store";
+
+import {ActivatedRouteSnapshot, Resolve} from "@angular/router";
+import {Observable} from "rxjs";
+import {AppState} from "../../store/reducers";
+import {InstantiationTemplatesService} from "../../services/templateService/instantiationTemplates.service";
+import {forkJoin} from "rxjs/observable/forkJoin";
+import {AaiService} from "../../services/aaiService/aai.service";
+import {ServiceInstance} from "../../models/serviceInstance";
+
+@Injectable()
+export class RecreateResolver implements Resolve<Observable<[any, ServiceInstance]>> {
+ constructor(private _templateService: InstantiationTemplatesService,
+ private _aaiService: AaiService,
+ private _store: NgRedux<AppState>) {
+ }
+
+ resolve(route: ActivatedRouteSnapshot): Observable<[any, ServiceInstance]> {
+ const serviceModelId: string = route.queryParamMap.get("serviceModelId");
+ const jobId: string = route.queryParamMap.get("jobId");
+
+ let serviceModelApi = this._aaiService.getServiceModelById(serviceModelId);
+ let instantiationTemplateApi = this._templateService.retrieveAndStoreInstantiationTemplateTopology(jobId, serviceModelId);
+
+ return forkJoin([serviceModelApi, instantiationTemplateApi])
+ }
+
+}
diff --git a/vid-webpack-master/src/app/shared/resolvers/viewEdit/viewEdit.resolver.ts b/vid-webpack-master/src/app/shared/resolvers/viewEdit/viewEdit.resolver.ts
index 540e02fe6..075e18f25 100644
--- a/vid-webpack-master/src/app/shared/resolvers/viewEdit/viewEdit.resolver.ts
+++ b/vid-webpack-master/src/app/shared/resolvers/viewEdit/viewEdit.resolver.ts
@@ -10,6 +10,7 @@ import {ServiceInstance} from "../../models/serviceInstance";
import * as _ from "lodash";
import {ModelInfo} from "../../models/modelInfo";
import {FeatureFlagsService, Features} from "../../services/featureFlag/feature-flags.service";
+import {Utils} from "../../utils/utils";
@Injectable()
export class ViewEditResolver implements Resolve<Observable<boolean>> {
@@ -69,7 +70,7 @@ export class ViewEditResolver implements Resolve<Observable<boolean>> {
};
setIsALaCarte(service: any, instantiationType) :void{
- service.isALaCarte = instantiationType === 'ALaCarte';
+ service.isALaCarte = Utils.isALaCarte(instantiationType);
};
}
diff --git a/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.spec.ts b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.spec.ts
index 147434b1a..0234ea514 100644
--- a/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.spec.ts
+++ b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.spec.ts
@@ -37,6 +37,25 @@ describe('Service Info Service', () => {
});
});
+ describe('#getServicesJobInfo', ()=> {
+ test('should call without serviceModelId', ()=>{
+ let job: ServiceInfoModel = new ServiceInfoModel();
+
+ service.getServicesJobInfo().subscribe();
+ const req = httpMock.expectOne(Constants.Path.SERVICES_JOB_INFO_PATH);
+
+ expect(req.request.method).toBe('GET');
+ });
+
+ test('should call with serviceModelId', ()=>{
+ let job: ServiceInfoModel = new ServiceInfoModel();
+
+ service.getServicesJobInfo(true, "123").subscribe();
+ const req = httpMock.expectOne(`${Constants.Path.SERVICES_JOB_INFO_PATH}?${Constants.Path.SERVICE_MODEL_ID}=123`);
+ expect(req.request.method).toBe('GET');
+ });
+ });
+
describe('#getALaCarteJobAuditStatus Without params', ()=> {
test('should return Observable<Object[]>', ()=>{
let job: ServiceInfoModel = new ServiceInfoModel();
diff --git a/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.ts b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.ts
index fe6ebc7ee..388afdba0 100644
--- a/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.ts
+++ b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.ts
@@ -2,8 +2,6 @@ import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {ServiceInfoModel} from './serviceInfo.model';
import {HttpClient, HttpHeaders} from '@angular/common/http';
-import { of } from 'rxjs';
-import { map } from 'rxjs/operators';
import {Constants} from '../../utils/constants';
import {forkJoin} from "rxjs/observable/forkJoin";
import * as _ from 'lodash';
@@ -14,10 +12,11 @@ export class ServiceInfoService {
constructor(private _http: HttpClient) {
}
- getServicesJobInfo(filterByUser : boolean, showSpinner: boolean = true): Observable<ServiceInfoModel[]> {
+ getServicesJobInfo(showSpinner: boolean = true, serviceModelId: string = null): Observable<ServiceInfoModel[]> {
let pathQuery = Constants.Path.SERVICES_JOB_INFO_PATH;
let headers = new HttpHeaders({'x-show-spinner': showSpinner.toString()});
- return this._http.get<ServiceInfoModel[]>(pathQuery, { headers: headers }).map(res => res );
+ let params = serviceModelId ? {serviceModelId} : {};
+ return this._http.get<ServiceInfoModel[]>(pathQuery, { headers: headers, params });
}
deleteJob(jobId: string): Observable<any> {
diff --git a/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.spec.ts b/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.spec.ts
index a34f2fe20..03461eaa1 100644
--- a/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.spec.ts
+++ b/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.spec.ts
@@ -32,6 +32,7 @@ describe('Default Data Generator Service', () => {
let result = service.generateVFModule(serviceHierarchy.vnfs[vnfUUID].vfModules[vnfModuleUUID], [], false, true);
expect(result.isMissingData).toBeTruthy();
+ expect(result.rollbackOnFailure).toBeTruthy();
});
test('generateVFModule should create vf module object', () => {
@@ -51,6 +52,7 @@ describe('Default Data Generator Service', () => {
expect(result.sdncPreReload).toBeNull();
expect(result.isMissingData).toBeTruthy();
expect(result.instanceParams).toEqual([{}]);
+ expect(result.rollbackOnFailure).toBeNull();
});
test('generateVNFData should create vnf object', () => {
diff --git a/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.ts b/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.ts
index b0baa82ec..a3cb475a0 100644
--- a/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.ts
+++ b/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.ts
@@ -186,7 +186,7 @@ export class DefaultDataGeneratorService {
for (let networkUUID in serviceHierarchy.networks) {
const isEcompGeneratedNaming = this.getIsEcompGeneratedNaming(serviceHierarchy.networks[networkUUID]);
let min_vnf_instances_greater_than_0 = serviceHierarchy.networks[networkUUID].properties['min_instances'] && serviceHierarchy.networks[networkUUID].properties['min_instances'] > 0;
- if(this.store.getState().global.flags['FLAG_DEFAULT_VNF'] && min_vnf_instances_greater_than_0)
+ if(min_vnf_instances_greater_than_0)
{
this.createNetworkInstanceReduxIfNotExist(
serviceId,
@@ -203,7 +203,7 @@ export class DefaultDataGeneratorService {
for (let vnfGroupUUID in serviceHierarchy.vnfGroups) {
const isEcompGeneratedNaming = this.getIsEcompGeneratedNaming(serviceHierarchy.vnfGroups[vnfGroupUUID]);
let min_vnf_group_instances_greater_than_0 = serviceHierarchy.vnfGroups[vnfGroupUUID].properties['min_instances'] && serviceHierarchy.vnfGroups[vnfGroupUUID].properties['min_instances'] > 0;
- if(this.store.getState().global.flags['FLAG_DEFAULT_VNF'] && min_vnf_group_instances_greater_than_0)
+ if(min_vnf_group_instances_greater_than_0)
{
this.createVnfGroupInstanceReduxIfNotExist(
serviceId,
@@ -244,7 +244,7 @@ export class DefaultDataGeneratorService {
}
let min_vnf_instances_greater_than_0 = serviceHierarchy.vnfs[vnfUUID].properties['min_instances'] && serviceHierarchy.vnfs[vnfUUID].properties['min_instances'] > 0;
- if(this.store.getState().global.flags['FLAG_DEFAULT_VNF'] && min_vnf_instances_greater_than_0)
+ if(min_vnf_instances_greater_than_0)
{
this.createVNFInstanceReduxIfNotExist(
serviceId,
@@ -328,6 +328,7 @@ export class DefaultDataGeneratorService {
instanceParams
],
'trackById': DefaultDataGeneratorService.createRandomTrackById(),
+ 'rollbackOnFailure' : isALaCarte ? true : null,
};
}
diff --git a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts
index d6c37c936..74fcd8f87 100644
--- a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts
+++ b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts
@@ -8,11 +8,14 @@ export enum Features {
FLAG_1902_VNF_GROUPING='FLAG_1902_VNF_GROUPING',
FLAG_VF_MODULE_RESUME_STATUS_CREATE = 'FLAG_VF_MODULE_RESUME_STATUS_CREATE',
FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE = 'FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE',
- FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE = 'FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE',
FLAG_1906_COMPONENT_INFO = 'FLAG_1906_COMPONENT_INFO',
FLAG_1908_RESUME_MACRO_SERVICE = 'FLAG_1908_RESUME_MACRO_SERVICE',
FLAG_FLASH_REPLACE_VF_MODULE ='FLAG_FLASH_REPLACE_VF_MODULE',
- FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT ='FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT'
+ FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT ='FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT',
+ FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS ='FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS',
+ FLAG_2004_INSTANTIATION_STATUS_FILTER ='FLAG_2004_INSTANTIATION_STATUS_FILTER',
+ FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE = 'FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE',
+ FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER ='FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER',
}
@Injectable()
@@ -24,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;
diff --git a/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.spec.ts b/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.spec.ts
new file mode 100644
index 000000000..80b113bde
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.spec.ts
@@ -0,0 +1,51 @@
+import {HttpClientTestingModule, HttpTestingController} from "@angular/common/http/testing";
+import {InstantiationTemplatesService} from "./instantiationTemplates.service";
+import {mock} from "ts-mockito";
+import {NgRedux} from "@angular-redux/store";
+import {getTestBed, TestBed} from "@angular/core/testing";
+import {ServiceInstance} from "../../models/serviceInstance";
+import {Constants} from "../../utils/constants";
+
+class MockAppStore<T> {
+ dispatch() {}
+ getState() {}
+}
+
+describe("TemplateService", ()=>{
+ let injector;
+ let httpMock: HttpTestingController;
+ let templateService: InstantiationTemplatesService;
+
+ beforeAll( done => (async () => {
+ TestBed.configureTestingModule({
+ imports: [HttpClientTestingModule],
+ providers: [
+ InstantiationTemplatesService,
+ {provide: NgRedux, useClass: MockAppStore},
+ ]
+ });
+ await TestBed.compileComponents();
+
+ injector = getTestBed();
+ httpMock = injector.get(HttpTestingController);
+ templateService = injector.get(InstantiationTemplatesService);
+ })().then(done).catch(done.fail));
+
+ describe ('#retrieveInstantiationTemplateTopology tests', () => {
+ test('when called -> retrieve template from backend', done => {
+ const mockedTemplate = mock(ServiceInstance);
+ const jobId: string = "some-random-job-id";
+
+ templateService.retrieveInstantiationTemplateTopology(jobId)
+ .subscribe((result: ServiceInstance) => {
+ expect(Object.is(result, mockedTemplate)).toBe(true);
+ done();
+ });
+
+ httpMock
+ .expectOne(`${Constants.Path.INSTANTIATION_TEMPLATE_TOPOLOGY}/${jobId}`)
+ .flush(mockedTemplate);
+ })
+ })
+});
+
diff --git a/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.ts b/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.ts
new file mode 100644
index 000000000..018e0d367
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.ts
@@ -0,0 +1,27 @@
+import {Injectable} from "@angular/core";
+import {HttpClient} from "@angular/common/http";
+import {NgRedux} from "@angular-redux/store";
+import {AppState} from "../../store/reducers";
+import {Observable} from "rxjs";
+import {ServiceInstance} from "../../models/serviceInstance";
+import {Constants} from "../../utils/constants";
+import {createServiceInstance} from "../../storeUtil/utils/service/service.actions";
+import {createServiceInstanceFromTemplate} from "../../storeUtil/utils/useTemplate/useTemplate.action";
+
+@Injectable()
+export class InstantiationTemplatesService {
+ constructor(private http: HttpClient, private store: NgRedux<AppState>) {
+ }
+
+ retrieveInstantiationTemplateTopology(jobId: string): Observable<ServiceInstance> {
+ let pathQuery: string = `${Constants.Path.INSTANTIATION_TEMPLATE_TOPOLOGY}/${jobId}`;
+ return this.http.get<ServiceInstance>(pathQuery)
+ }
+
+ public retrieveAndStoreInstantiationTemplateTopology(jobId: string, serviceModelId: string): Observable<ServiceInstance> {
+ return this.retrieveInstantiationTemplateTopology(jobId).do((instantiationTemplate: ServiceInstance) => {
+ this.store.dispatch(createServiceInstanceFromTemplate(instantiationTemplate, serviceModelId));
+ });
+ };
+
+}
diff --git a/vid-webpack-master/src/app/shared/shared.module.ts b/vid-webpack-master/src/app/shared/shared.module.ts
index 93452256b..273dff472 100644
--- a/vid-webpack-master/src/app/shared/shared.module.ts
+++ b/vid-webpack-master/src/app/shared/shared.module.ts
@@ -42,6 +42,7 @@ import {NetworkPopupService} from "./components/genericFormPopup/genericFormServ
import {NetworkControlGenerator} from "./components/genericForm/formControlsServices/networkGenerator/network.control.generator";
import {BasicPopupService} from "./components/genericFormPopup/genericFormServices/basic.popup.service";
import {VfModulePopuopService} from "./components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service";
+import {VfModuleUpgradePopupService} from "./components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
import {VfModuleControlGenerator} from "./components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator";
import {OrderByPipe} from "./pipes/order/orderBy.pipe";
import {ServicePopupService} from "./components/genericFormPopup/genericFormServices/service/service.popup.service";
@@ -72,6 +73,12 @@ import {ClickOutsideDirective} from "./directives/clickOutside/clickOutside.dire
import {DynamicInputsComponent} from "./components/dynamic-inputs/dynamic-inputs.component";
import {DynamicInputLabelPipe} from "./pipes/dynamicInputLabel/dynamic-input-label.pipe";
import {ModelInformationService} from "./components/model-information/model-information.service";
+import {MultiselectFormControlService} from "./components/formControls/component/multiselect/multiselect.formControl.service";
+import {InstantiationTemplatesModalComponent} from "./components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component";
+import {InstantiationTemplatesModalService} from "./components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service";
+import {SearchFilterPipe} from "./pipes/searchFilter/search-filter.pipe";
+import {RecreateResolver} from "./resolvers/recreate/recreate.resolver";
+import {InstantiationTemplatesService} from "./services/templateService/instantiationTemplates.service";
@NgModule({
@@ -112,6 +119,7 @@ import {ModelInformationService} from "./components/model-information/model-info
SafePipe,
ObjectToArrayPipe,
DataFilterPipe,
+ SearchFilterPipe,
InputFormControlComponent,
FormControlMessageErrorComponent,
GenericFormPopupComponent,
@@ -123,7 +131,8 @@ import {ModelInformationService} from "./components/model-information/model-info
SvgComponent,
ErrorMsgComponent,
DynamicInputsComponent,
- DynamicInputLabelPipe
+ DynamicInputLabelPipe,
+ InstantiationTemplatesModalComponent
],
exports: [
PopoverComponent,
@@ -143,6 +152,7 @@ import {ModelInformationService} from "./components/model-information/model-info
SafePipe,
ObjectToArrayPipe,
DataFilterPipe,
+ SearchFilterPipe,
InputFormControlComponent,
FormControlMessageErrorComponent,
GenericFormPopupComponent,
@@ -158,7 +168,8 @@ import {ModelInformationService} from "./components/model-information/model-info
],
entryComponents : [
GenericFormPopupComponent,
- SearchElementsModalComponent
+ SearchElementsModalComponent,
+ InstantiationTemplatesModalComponent
],
providers: [
ServiceInfoService,
@@ -173,6 +184,8 @@ import {ModelInformationService} from "./components/model-information/model-info
FlagsResolve,
ViewEditResolver,
RetryResolver,
+ RecreateResolver,
+ InstantiationTemplatesService,
ServiceControlGenerator,
ServicePopupService,
VnfControlGenerator,
@@ -181,6 +194,7 @@ import {ModelInformationService} from "./components/model-information/model-info
CustomValidators,
NetworkPopupService,
VfModulePopuopService,
+ VfModuleUpgradePopupService,
NetworkControlGenerator,
VnfGroupControlGenerator,
VnfGroupPopupService,
@@ -193,7 +207,10 @@ import {ModelInformationService} from "./components/model-information/model-info
ElementsTableService,
ErrorMsgService,
DataFilterPipe,
+ SearchFilterPipe,
ModelInformationService,
+ MultiselectFormControlService,
+ InstantiationTemplatesModalService
]
})
export class SharedModule {
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.actions.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.actions.ts
index 7a10eba0a..79dd3c717 100644
--- a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.actions.ts
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.actions.ts
@@ -5,6 +5,7 @@ import {ServiceType} from "../../../models/serviceType";
import {ITreeNode} from "angular-tree-component/dist/defs/api";
export enum GeneralActions {
+ MERGE_OBJECT_BY_PATH = "MERGE_OBJECT_BY_PATH",
UPDATE_LCP_REGIONS_AND_TENANTS = "UPDATE_LCP_REGIONS_AND_TENANTS",
UPDATE_SUBSCRIBERS = "UPDATE_SUBSCRIBERS",
UPDATE_PRODUCT_FAMILIES = "UPDATE_PRODUCT_FAMILIES",
@@ -78,6 +79,11 @@ export interface UpdateServiceTypesAction extends Action {
subscriberId: string;
}
+export interface MergeObjectByPathAction extends Action{
+ path: String[];
+ payload: object;
+}
+
export const updateLcpRegionsAndTenants: ActionCreator<UpdateLcpRegionsAndTenantsAction> = lcpRegionsAndTenants => ({
type: GeneralActions.UPDATE_LCP_REGIONS_AND_TENANTS,
lcpRegionsAndTenants: lcpRegionsAndTenants
@@ -147,4 +153,10 @@ export const updateServiceTypes: ActionCreator<UpdateServiceTypesAction> = (serv
subscriberId: subscriberId
});
+export const mergeObjectByPathAction : ActionCreator<MergeObjectByPathAction> = (path, payload) => ({
+ type: GeneralActions.MERGE_OBJECT_BY_PATH,
+ path,
+ payload
+});
+
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.spec.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.spec.ts
index ed456314e..952a92842 100644
--- a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.spec.ts
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.spec.ts
@@ -1,22 +1,12 @@
import {LcpRegion} from "../../../models/lcpRegion";
import {Tenant} from "../../../models/tenant";
import {generalReducer} from "./general.reducers";
-import {
- ChangeInstanceCounterAction,
- RemoveInstanceAction,
- DuplicateBulkInstancesAction,
- GeneralActions,
- UpdateAicZonesAction,
- UpdateCategoryParametersAction,
- UpdateProductFamiliesAction,
- UpdateServiceTypesAction,
- UpdateSubscribersAction,
- UpdateUserIdAction, UpdateNetworkCollectionFunction,
-} from "./general.actions";
+import {ChangeInstanceCounterAction, DuplicateBulkInstancesAction, GeneralActions, MergeObjectByPathAction, RemoveInstanceAction, UpdateAicZonesAction, UpdateCategoryParametersAction, UpdateNetworkCollectionFunction, UpdateProductFamiliesAction, UpdateServiceTypesAction, UpdateSubscribersAction, UpdateUserIdAction,} from "./general.actions";
import {SelectOption} from "../../../models/selectOption";
import {ServiceType} from "../../../models/serviceType";
import {ITreeNode} from "angular-tree-component/dist/defs/api";
import {VnfInstance} from "../../../models/vnfInstance";
+import each from "jest-each";
describe('generalReducer', () => {
test('#UPDATE_LCP_REGIONS_AND_TENANTS : should update lcp region and tenants', () => {
@@ -370,6 +360,45 @@ describe('generalReducer', () => {
expect(state).toBeDefined();
expect(state['networkFunctions']).toBeDefined();
});
+
+ const originalMockObject = {
+ remain: 'forever',
+ obsolete: 'toBeChange'
+ };
+
+ each([
+ [
+ ['serviceInstance', 'serviceModelId', 'vnfs'],
+ {
+ remain: 'forever',
+ obsolete: 'newValue',
+ newField: 'newValue2'
+ }
+ ],
+ [
+ ['serviceInstance', 'nowhere', 'somewhere'],
+ originalMockObject
+ ],
+ ]).
+ test('#MERGE_OBJECT_BY_PATH: should update some object by path %s', (path, expected) => {
+ let state = generalReducer(<any>{serviceInstance : {
+ 'serviceModelId' : {
+ vnfs : originalMockObject,
+ existingVNFCounterMap : {}
+ }
+ }},
+ <MergeObjectByPathAction>{
+ type: GeneralActions.MERGE_OBJECT_BY_PATH,
+ path,
+ payload: {
+ obsolete: 'newValue',
+ newField: 'newValue2'
+ }
+ });
+
+ expect(state).toBeDefined();
+ expect(state.serviceInstance['serviceModelId'].vnfs).toEqual(expected);
+ });
});
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.ts
index 5b265dbfd..f87a97397 100644
--- a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.ts
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.ts
@@ -1,12 +1,5 @@
import {Action} from "redux";
-import {
- ChangeInstanceCounterAction, RemoveInstanceAction, DuplicateBulkInstancesAction,
- GeneralActions,
- UpdateAicZonesAction, UpdateCategoryParametersAction,
- UpdateLcpRegionsAndTenantsAction, UpdateNetworkCollectionFunction,
- UpdateProductFamiliesAction, UpdateServiceTypesAction,
- UpdateSubscribersAction, UpdateUserIdAction
-} from "./general.actions";
+import {ChangeInstanceCounterAction, DuplicateBulkInstancesAction, GeneralActions, MergeObjectByPathAction, RemoveInstanceAction, UpdateAicZonesAction, UpdateCategoryParametersAction, UpdateLcpRegionsAndTenantsAction, UpdateNetworkCollectionFunction, UpdateProductFamiliesAction, UpdateServiceTypesAction, UpdateSubscribersAction, UpdateUserIdAction} from "./general.actions";
import {TypeNodeInformation} from "../../../../drawingBoard/service-planning/typeNodeInformation.model";
import * as _ from "lodash";
import {ITreeNode} from "angular-tree-component/dist/defs/api";
@@ -92,6 +85,19 @@ export function generalReducer(state: ServiceState, action: Action) : ServiceSta
return newState;
}
+ case GeneralActions.MERGE_OBJECT_BY_PATH : {
+ const mergeObjectByPathAction = <MergeObjectByPathAction>action;
+ let newState = _.cloneDeep(state);
+ let targetObject = _.get(newState, <any>mergeObjectByPathAction.path);
+ if (targetObject) {
+ targetObject = _.merge(targetObject, mergeObjectByPathAction.payload);
+ }
+ else {
+ console.error(`Can't find object at ${mergeObjectByPathAction.path.join()}`)
+ }
+ return newState;
+ }
+
}
}
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/main.reducer.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/main.reducer.ts
index c02049eb9..a135563eb 100644
--- a/vid-webpack-master/src/app/shared/storeUtil/utils/main.reducer.ts
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/main.reducer.ts
@@ -9,9 +9,11 @@ import {VNFActions} from "./vnf/vnf.actions";
import {vnfReducer} from "./vnf/vnf.reducers";
import {generalReducer} from "./general/general.reducers";
import {serviceReducer} from "./service/service.reducers";
+import {useTemplateReducer} from "./useTemplate/useTemplate.reducer";
import {networkReducer} from "./network/network.reducers";
import {vfModuleReducer} from "./vfModule/vfModule.reducers";
import {ServiceInstance} from "../../models/serviceInstance";
+import {UseTemplateActions} from "./useTemplate/useTemplate.action";
import {SelectOptionInterface} from "../../models/selectOption";
import {ServiceType} from "../../models/serviceType";
import {VnfGroupActions} from "./vnfGroup/vnfGroup.actions";
@@ -72,6 +74,8 @@ export const MainReducer = function (state: ServiceState = initialState, action:
return crReducer(state, action);
}else if(Object.values(NcfActions).includes(action.type)){
return ncfReducer(state, action);
+ } else if(Object.values(UseTemplateActions).includes(action.type)) {
+ return useTemplateReducer(state, action);
} else {
return Object.assign({}, state);
}
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.action.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.action.ts
new file mode 100644
index 000000000..2cfd38482
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.action.ts
@@ -0,0 +1,17 @@
+import {Action, ActionCreator} from "redux";
+import {ServiceInstance} from "../../../models/serviceInstance";
+
+export enum UseTemplateActions {
+ CREATE_SERVICE_INSTANCE_FROM_TEMPLATE = 'CREATE_SERVICE_INSTANCE_FROM_TEMPLATE',
+}
+
+export interface CreateServiceInstanceFromTemplate extends Action {
+ serviceInstantiationTemplate?: ServiceInstance;
+ serviceModelId?: string;
+}
+
+export const createServiceInstanceFromTemplate: ActionCreator<CreateServiceInstanceFromTemplate> = (serviceInstantiationTemplate, serviceModelId) => ({
+ type: UseTemplateActions.CREATE_SERVICE_INSTANCE_FROM_TEMPLATE,
+ serviceInstantiationTemplate: serviceInstantiationTemplate,
+ serviceModelId: serviceModelId
+});
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.spec.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.spec.ts
new file mode 100644
index 000000000..e0f46e13a
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.spec.ts
@@ -0,0 +1,18 @@
+import {ServiceInstance} from "../../../models/serviceInstance";
+import {useTemplateReducer} from "./useTemplate.reducer";
+import {CreateServiceInstanceFromTemplate, UseTemplateActions} from "./useTemplate.action";
+
+test('#CREATE_SERVICE_INSTANCE_FROM_TEMPLATE should add new service instance from template to redux ', () => {
+ let serviceFromTemplateInstance: ServiceInstance = <any>{
+ instanceName: 'templateInstanceName'
+ };
+ let serviceState = useTemplateReducer(<any>{
+ serviceInstance:{}},
+ <CreateServiceInstanceFromTemplate> {
+ type: UseTemplateActions.CREATE_SERVICE_INSTANCE_FROM_TEMPLATE,
+ serviceModelId: 'serviceModelID',
+ serviceInstantiationTemplate: serviceFromTemplateInstance,
+ })
+ expect (serviceState).toBeDefined();
+ expect (serviceState.serviceInstance['serviceModelID'].instanceName).toEqual('templateInstanceName');
+});
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.ts
new file mode 100644
index 000000000..5a06d6e0a
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.ts
@@ -0,0 +1,20 @@
+import {ServiceState} from "../main.reducer";
+import {Action} from "redux";
+import {
+ createServiceInstanceFromTemplate,
+ CreateServiceInstanceFromTemplate,
+ UseTemplateActions
+} from "./useTemplate.action";
+import * as _ from "lodash";
+
+export function useTemplateReducer(state: ServiceState, action: Action) : ServiceState {
+ switch (action.type) {
+ case UseTemplateActions.CREATE_SERVICE_INSTANCE_FROM_TEMPLATE : {
+ const updateServiceInstanceFromTemplateAction = <CreateServiceInstanceFromTemplate>action;
+ const uuid = updateServiceInstanceFromTemplateAction.serviceModelId;
+ let newState = _.cloneDeep(state);
+ newState.serviceInstance[uuid] = updateServiceInstanceFromTemplateAction.serviceInstantiationTemplate;
+ return newState;
+ }
+ }
+}
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.actions.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.actions.ts
index 59e5ee1fa..70c10c429 100644
--- a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.actions.ts
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.actions.ts
@@ -9,6 +9,8 @@ export enum VfModuleActions {
UPDATE_VFMODULE_POSITION = "UPDATE_VFMODULE_POSITION",
UPGRADE_VFMODULE = "UPGRADE_VFMODULE",
UNDO_UPGRADE_VFMODULE_ACTION = "UNDO_UPGRADE_VFMODULE_ACTION",
+ UPDATE_VFMODULE_FEILD = "UPDATE_VFMODULE_FEILD",
+ DELETE_VFMODULE_FEILD = "DELETE_VFMODULE_FEILD",
}
@@ -62,6 +64,23 @@ export interface UndoUpgradeVfModuleInstanceAction extends Action {
dynamicModelName: string;
}
+export interface UpdateVFModuleField extends Action {
+ modelName : string;
+ vnfStoreKey : string;
+ serviceId: string;
+ dynamicModelName: string;
+ fieldName: string;
+ fieldValue : any;
+}
+
+export interface DeleteVFModuleField extends Action {
+ modelName : string;
+ vnfStoreKey : string;
+ serviceId: string;
+ dynamicModelName: string;
+ deleteFieldName: string;
+}
+
export interface UndoDeleteActionVfModuleInstanceAction extends Action {
dynamicModelName: string;
vnfStoreKey : string;
@@ -132,3 +151,22 @@ export const undoUgradeVFModule: ActionCreator<UndoUpgradeVfModuleInstanceAction
vnfStoreKey,
serviceId
});
+
+export const updateVFModuleField: ActionCreator<UpdateVFModuleField> = (modelName, vnfStoreKey, serviceId, dynamicModelName, fieldName, fieldValue) => ({
+ type: VfModuleActions.UPDATE_VFMODULE_FEILD,
+ dynamicModelName,
+ modelName,
+ vnfStoreKey,
+ serviceId,
+ fieldName,
+ fieldValue
+});
+
+export const deleteVFModuleField: ActionCreator<DeleteVFModuleField> = (modelName, vnfStoreKey, serviceId, dynamicModelName, deleteFieldName) => ({
+ type: VfModuleActions.DELETE_VFMODULE_FEILD,
+ dynamicModelName,
+ modelName,
+ vnfStoreKey,
+ serviceId,
+ deleteFieldName
+});
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.spec.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.spec.ts
index ee0edb0a7..7b890b715 100644
--- a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.spec.ts
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.spec.ts
@@ -1,9 +1,9 @@
import {
CreateVFModuleInstanceAction,
- DeleteActionVfModuleInstanceAction,
+ DeleteActionVfModuleInstanceAction, DeleteVFModuleField,
DeleteVfModuleInstanceAction,
UndoDeleteActionVfModuleInstanceAction,
- UpdateVFModluePosition,
+ UpdateVFModluePosition, UpdateVFModuleField,
UpgradeVfModuleInstanceAction,
VfModuleActions
} from "./vfModule.actions";
@@ -14,12 +14,13 @@ import {ServiceInstanceActions} from "../../../models/serviceInstanceActions";
describe('vfModuleReducer', () => {
test('#REMOVE_VNF_MODULE_INSTANCE : should delete existing vnf module by dynamicModelName', () => {
- let state = vfModuleReducer(<any>{serviceInstance : {
- 'serviceModelId' : {
- vnfs : {
- 'vfName' : {
- vfModules : {
- 'modelName' : {
+ let state = vfModuleReducer(<any>{
+ serviceInstance: {
+ 'serviceModelId': {
+ vnfs: {
+ 'vfName': {
+ vfModules: {
+ 'modelName': {
'dynamicModelName1': {},
'dynamicModelName2': {},
}
@@ -27,13 +28,14 @@ describe('vfModuleReducer', () => {
}
}
}
- }},
+ }
+ },
<DeleteVfModuleInstanceAction>{
type: VfModuleActions.REMOVE_VNF_MODULE_INSTANCE,
- modelName : 'modelName',
- vfName : 'vfName',
- vnfStoreKey : 'vfName',
- serviceModelId : 'serviceModelId',
+ modelName: 'modelName',
+ vfName: 'vfName',
+ vnfStoreKey: 'vfName',
+ serviceModelId: 'serviceModelId',
dynamicModelName: 'dynamicModelName1'
});
@@ -43,26 +45,27 @@ describe('vfModuleReducer', () => {
});
test('#DELETE_LAST_VNF_MODULE_INSTANCE : should delete existing vnf module', () => {
- let state = vfModuleReducer(<any>{serviceInstance : {
- 'serviceModelId' : {
- vnfs : {
- 'vfName' : {
- vfModules : {
- 'modelName' : {
- 'dynamicModelName': {
- }
+ let state = vfModuleReducer(<any>{
+ serviceInstance: {
+ 'serviceModelId': {
+ vnfs: {
+ 'vfName': {
+ vfModules: {
+ 'modelName': {
+ 'dynamicModelName': {}
}
}
}
}
}
- }},
+ }
+ },
<DeleteVfModuleInstanceAction>{
type: VfModuleActions.REMOVE_VNF_MODULE_INSTANCE,
- modelName : 'modelName',
- vfName : 'vfName',
- vnfStoreKey : 'vfName',
- serviceModelId : 'serviceModelId',
+ modelName: 'modelName',
+ vfName: 'vfName',
+ vnfStoreKey: 'vfName',
+ serviceModelId: 'serviceModelId',
dynamicModelName: 'dynamicModelName'
});
@@ -70,28 +73,29 @@ describe('vfModuleReducer', () => {
expect(state.serviceInstance['serviceModelId'].vnfs['vfName'].vfModules['modelName']).not.toBeDefined();
});
- test('#CREATE_VF_MODULE: should create new vfModule to existing VNF', ()=>{
- let vfModuleInstance : VfModuleInstance = new VfModuleInstance();
+ test('#CREATE_VF_MODULE: should create new vfModule to existing VNF', () => {
+ let vfModuleInstance: VfModuleInstance = new VfModuleInstance();
vfModuleInstance.instanceName = 'instanceName';
vfModuleInstance.isMissingData = false;
vfModuleInstance.volumeGroupName = 'volumeGroupName';
- let vfModule = vfModuleReducer(<any>{serviceInstance : {
- 'serviceUuid' : {
- vnfs : {
- 'vnfStoreKey' : {
- 'vfModules' : {
- }
+ let vfModule = vfModuleReducer(<any>{
+ serviceInstance: {
+ 'serviceUuid': {
+ vnfs: {
+ 'vnfStoreKey': {
+ 'vfModules': {}
}
}
}
- }},
+ }
+ },
<CreateVFModuleInstanceAction>{
type: VfModuleActions.CREATE_VF_MODULE,
- vfId : 'vfId',
- vfInstance : new VfModuleInstance(),
- vnfStoreKey : 'vnfStoreKey',
- serviceUuid : 'serviceUuid',
- index : 1
+ vfId: 'vfId',
+ vfInstance: new VfModuleInstance(),
+ vnfStoreKey: 'vnfStoreKey',
+ serviceUuid: 'serviceUuid',
+ index: 1
}).serviceInstance['serviceUuid'].vnfs['vnfStoreKey'].vfModules;
let firstVfModuleName = Object.keys(vfModule)[0];
@@ -99,23 +103,64 @@ describe('vfModuleReducer', () => {
expect(vfModule[firstVfModuleName].isMissingData).toBeFalsy();
});
- test('#UPDATE_VF_MODULE: should update existing VFModule', ()=>{
- let vfModuleInstance : VfModuleInstance = new VfModuleInstance();
- vfModuleInstance.instanceName = 'instanceName';
- vfModuleInstance.isMissingData = false;
- vfModuleInstance.volumeGroupName = 'volumeGroupName';
- let vfModule = vfModuleReducer(<any>{
- serviceHierarchy : {
- 'serviceModelId' : {}
+ test('#UPDATE_VFMODULE_FEILD: should update field with some value', () => {
+ const newFieldName = 'newFieldName';
+ const newFieldValue = 'newFieldValue';
+ let oldState = {
+ serviceHierarchy: {
+ 'serviceModelId': {}
+ },
+ serviceInstance: {
+ 'serviceModelId': {
+ vnfs: {
+ 'vnfStoreKey': {
+ vfModules: {
+ 'modelName': {
+ 'dynamicModelName1': {
+ isMissingData: true,
+ action: 'None'
+ },
+ 'dynamicModelName2': {},
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+
+ let newState = vfModuleReducer(<any>oldState,
+ <UpdateVFModuleField>{
+ type: VfModuleActions.UPDATE_VFMODULE_FEILD,
+ dynamicModelName: 'dynamicModelName1',
+ vnfStoreKey: 'vnfStoreKey',
+ serviceId: 'serviceModelId',
+ modelName: 'modelName',
+ fieldName: newFieldName,
+ fieldValue: newFieldValue
+ });
+
+ let vfModule = newState.serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
+
+ expect(vfModule[newFieldName]).toEqual(newFieldValue);
+ });
+
+ test('#DELETE_VFMODULE_FEILD: should update field with some value', () => {
+ const deleteFieldName = 'deleteFieldName';
+ let oldState = {
+ serviceHierarchy: {
+ 'serviceModelId': {}
},
- serviceInstance : {
- 'serviceModelId' : {
- vnfs : {
- 'vfName' : {
- vfModules : {
- 'modelName' : {
+ serviceInstance: {
+ 'serviceModelId': {
+ vnfs: {
+ 'vnfStoreKey': {
+ vfModules: {
+ 'modelName': {
'dynamicModelName1': {
- isMissingData : true
+ isMissingData: true,
+ [deleteFieldName]: true,
+ action: 'None'
},
'dynamicModelName2': {},
}
@@ -123,192 +168,197 @@ describe('vfModuleReducer', () => {
}
}
}
- }},
- <CreateVFModuleInstanceAction>{
- type: VfModuleActions.UPDATE_VF_MODULE,
- vfId : 'modelName',
- vfInstance : new VfModuleInstance(),
- vnfStoreKey : 'vfName',
- dynamicModelName : 'dynamicModelName1',
- serviceUuid : 'serviceModelId',
- index : 1
- }).serviceInstance['serviceModelId'].vnfs['vfName'].vfModules;
+ }
+ };
+ let newState = vfModuleReducer(<any>oldState,
+ <DeleteVFModuleField>{
+ type: VfModuleActions.DELETE_VFMODULE_FEILD,
+ dynamicModelName: 'dynamicModelName1',
+ vnfStoreKey: 'vnfStoreKey',
+ serviceId: 'serviceModelId',
+ modelName: 'modelName',
+ deleteFieldName: deleteFieldName,
+ });
- let firstVfModuleName = Object.keys(vfModule)[0];
- expect(vfModule[firstVfModuleName]).toBeDefined();
- expect(vfModule[firstVfModuleName].isMissingData).toBeFalsy();
- });
+ let vfModule = newState.serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
+ expect(vfModule[deleteFieldName]).toBeUndefined();
+});
- test('#UPDATE_VFMODULE_POSITION: should update position', ()=>{
- let vfModule = vfModuleReducer(<any>{
- serviceHierarchy : {
- 'serviceModelId' : {}
- },
- serviceInstance : {
- 'serviceModelId' : {
- vnfs : {
- 'vfName' : {
- vfModules : {
- 'modelName' : {
- 'dynamicModelName': {
- isMissingData : true
- }
+test('#UPDATE_VFMODULE_POSITION: should update position', () => {
+ let vfModule = vfModuleReducer(<any>{
+ serviceHierarchy: {
+ 'serviceModelId': {}
+ },
+ serviceInstance: {
+ 'serviceModelId': {
+ vnfs: {
+ 'vfName': {
+ vfModules: {
+ 'modelName': {
+ 'dynamicModelName': {
+ isMissingData: true
}
}
}
}
}
- }},
- <UpdateVFModluePosition>{
- type: VfModuleActions.UPDATE_VFMODULE_POSITION,
- node: {
- position : 1,
- dynamicModelName : "dynamicModelName",
- modelName : "modelName"
- },
- instanceId : "serviceModelId",
- vnfStoreKey : "vfName"
+ }
+ }
+ },
+ <UpdateVFModluePosition>{
+ type: VfModuleActions.UPDATE_VFMODULE_POSITION,
+ node: {
+ position: 1,
+ dynamicModelName: "dynamicModelName",
+ modelName: "modelName"
+ },
+ instanceId: "serviceModelId",
+ vnfStoreKey: "vfName"
- }).serviceInstance['serviceModelId'].vnfs['vfName'].vfModules["modelName"]["dynamicModelName"];
-
- expect(vfModule.position).toEqual(1);
- });
+ }).serviceInstance['serviceModelId'].vnfs['vfName'].vfModules["modelName"]["dynamicModelName"];
+ expect(vfModule.position).toEqual(1);
+});
- test('#DELETE_ACTION_VF_MODULE_INSTANCE', ()=>{
- let vfModule = vfModuleReducer(<any>{
- serviceHierarchy : {
- 'serviceModelId' : {}
- },
- serviceInstance : {
- 'serviceModelId' : {
- vnfs : {
- 'vnfStoreKey' : {
- vfModules : {
- 'modelName' : {
- 'dynamicModelName1': {
- isMissingData : true,
- action : 'None'
- },
- 'dynamicModelName2': {},
- }
+test('#DELETE_ACTION_VF_MODULE_INSTANCE', () => {
+ let vfModule = vfModuleReducer(<any>{
+ serviceHierarchy: {
+ 'serviceModelId': {}
+ },
+ serviceInstance: {
+ 'serviceModelId': {
+ vnfs: {
+ 'vnfStoreKey': {
+ vfModules: {
+ 'modelName': {
+ 'dynamicModelName1': {
+ isMissingData: true,
+ action: 'None'
+ },
+ 'dynamicModelName2': {},
}
}
}
}
- }},
- <DeleteActionVfModuleInstanceAction>{
- type: VfModuleActions.DELETE_ACTION_VF_MODULE_INSTANCE,
- dynamicModelName: 'dynamicModelName1',
- vnfStoreKey : 'vnfStoreKey',
- serviceId: 'serviceModelId'
- }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
+ }
+ }
+ },
+ <DeleteActionVfModuleInstanceAction>{
+ type: VfModuleActions.DELETE_ACTION_VF_MODULE_INSTANCE,
+ dynamicModelName: 'dynamicModelName1',
+ vnfStoreKey: 'vnfStoreKey',
+ serviceId: 'serviceModelId'
+ }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
- console.log(vfModule.action);
- expect(vfModule).toBeDefined();
- expect(vfModule.isMissingData).toBeTruthy();
- expect(vfModule.action).toEqual(ServiceInstanceActions.None_Delete);
- });
+ console.log(vfModule.action);
+ expect(vfModule).toBeDefined();
+ expect(vfModule.isMissingData).toBeTruthy();
+ expect(vfModule.action).toEqual(ServiceInstanceActions.None_Delete);
+});
- test('#UNDO_DELETE_ACTION_VF_MODULE_INSTANCE', ()=>{
- let vfModule = vfModuleReducer(<any>{
- serviceHierarchy : {
- 'serviceModelId' : {}
- },
- serviceInstance : {
- 'serviceModelId' : {
- vnfs : {
- 'vnfStoreKey' : {
- vfModules : {
- 'modelName' : {
- 'dynamicModelName1': {
- isMissingData : true,
- action : 'None_Delete'
- },
- 'dynamicModelName2': {},
- }
+test('#UNDO_DELETE_ACTION_VF_MODULE_INSTANCE', () => {
+ let vfModule = vfModuleReducer(<any>{
+ serviceHierarchy: {
+ 'serviceModelId': {}
+ },
+ serviceInstance: {
+ 'serviceModelId': {
+ vnfs: {
+ 'vnfStoreKey': {
+ vfModules: {
+ 'modelName': {
+ 'dynamicModelName1': {
+ isMissingData: true,
+ action: 'None_Delete'
+ },
+ 'dynamicModelName2': {},
}
}
}
}
- }},
- <UndoDeleteActionVfModuleInstanceAction>{
- type: VfModuleActions.UNDO_DELETE_ACTION_VF_MODULE_INSTANCE,
- dynamicModelName: 'dynamicModelName1',
- vnfStoreKey : 'vnfStoreKey',
- serviceId: 'serviceModelId'
- }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
+ }
+ }
+ },
+ <UndoDeleteActionVfModuleInstanceAction>{
+ type: VfModuleActions.UNDO_DELETE_ACTION_VF_MODULE_INSTANCE,
+ dynamicModelName: 'dynamicModelName1',
+ vnfStoreKey: 'vnfStoreKey',
+ serviceId: 'serviceModelId'
+ }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
- console.log(vfModule.action);
- expect(vfModule).toBeDefined();
- expect(vfModule.action).toEqual(ServiceInstanceActions.None);
- });
+ console.log(vfModule.action);
+ expect(vfModule).toBeDefined();
+ expect(vfModule.action).toEqual(ServiceInstanceActions.None);
+});
- test('#UPGRADE_VFMODULE', ()=>{
- let vfModule = vfModuleReducer(<any>{
- serviceHierarchy : {
- 'serviceModelId' : {}
- },
- serviceInstance : {
- 'serviceModelId' : {
- vnfs : {
- 'vnfStoreKey' : {
- vfModules : {
- 'modelName' : {
- 'dynamicModelName1': {
- isMissingData : true,
- action : 'None'
- },
- 'dynamicModelName2': {},
- }
+test('#UPGRADE_VFMODULE', () => {
+ let vfModule = vfModuleReducer(<any>{
+ serviceHierarchy: {
+ 'serviceModelId': {}
+ },
+ serviceInstance: {
+ 'serviceModelId': {
+ vnfs: {
+ 'vnfStoreKey': {
+ vfModules: {
+ 'modelName': {
+ 'dynamicModelName1': {
+ isMissingData: true,
+ action: 'None'
+ },
+ 'dynamicModelName2': {},
}
}
}
}
- }},
- <UpgradeVfModuleInstanceAction>{
- type: VfModuleActions.UPGRADE_VFMODULE,
- dynamicModelName: 'dynamicModelName1',
- vnfStoreKey : 'vnfStoreKey',
- serviceId: 'serviceModelId',
- modelName: 'modelName'
- }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
+ }
+ }
+ },
+ <UpgradeVfModuleInstanceAction>{
+ type: VfModuleActions.UPGRADE_VFMODULE,
+ dynamicModelName: 'dynamicModelName1',
+ vnfStoreKey: 'vnfStoreKey',
+ serviceId: 'serviceModelId',
+ modelName: 'modelName'
+ }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
- expect(vfModule.action).toEqual(ServiceInstanceActions.None_Upgrade);
- });
+ expect(vfModule.action).toEqual(ServiceInstanceActions.None_Upgrade);
+});
- test('#UNDO_UPGRADE_VFMODULE', ()=>{
- let vfModule = vfModuleReducer(<any>{
- serviceHierarchy : {
- 'serviceModelId' : {}
- },
- serviceInstance : {
- 'serviceModelId' : {
- vnfs : {
- 'vnfStoreKey' : {
- vfModules : {
- 'modelName' : {
- 'dynamicModelName1': {
- isMissingData : true,
- action : 'None_Upgrade'
- },
- 'dynamicModelName2': {},
- }
+test('#UNDO_UPGRADE_VFMODULE', () => {
+ let vfModule = vfModuleReducer(<any>{
+ serviceHierarchy: {
+ 'serviceModelId': {}
+ },
+ serviceInstance: {
+ 'serviceModelId': {
+ vnfs: {
+ 'vnfStoreKey': {
+ vfModules: {
+ 'modelName': {
+ 'dynamicModelName1': {
+ isMissingData: true,
+ action: 'None_Upgrade'
+ },
+ 'dynamicModelName2': {},
}
}
}
}
- }},
- <UpgradeVfModuleInstanceAction>{
- type: VfModuleActions.UNDO_UPGRADE_VFMODULE_ACTION,
- dynamicModelName: 'dynamicModelName1',
- vnfStoreKey : 'vnfStoreKey',
- serviceId: 'serviceModelId',
- modelName: 'modelName'
- }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
-
- expect(vfModule.action).toEqual(ServiceInstanceActions.None);
- });
+ }
+ }
+ },
+ <UpgradeVfModuleInstanceAction>{
+ type: VfModuleActions.UNDO_UPGRADE_VFMODULE_ACTION,
+ dynamicModelName: 'dynamicModelName1',
+ vnfStoreKey: 'vnfStoreKey',
+ serviceId: 'serviceModelId',
+ modelName: 'modelName'
+ }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1'];
+ expect(vfModule.action).toEqual(ServiceInstanceActions.None);
});
+
+})
+;
diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.ts
index a7aadba41..1bb2b15fd 100644
--- a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.ts
+++ b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.ts
@@ -1,10 +1,10 @@
import {Action} from "redux";
import * as _ from "lodash";
import {
- CreateVFModuleInstanceAction, DeleteActionVfModuleInstanceAction,
- DeleteVfModuleInstanceAction, UndoDeleteActionVfModuleInstanceAction, UpdateVFModluePosition,
+ CreateVFModuleInstanceAction, DeleteActionVfModuleInstanceAction, DeleteVFModuleField,
+ DeleteVfModuleInstanceAction, UndoDeleteActionVfModuleInstanceAction, UpdateVFModluePosition, UpdateVFModuleField,
UpdateVFModuleInstanceAction, UpgradeVfModuleInstanceAction,
- VfModuleActions
+ VfModuleActions,
} from "./vfModule.actions";
import {ServiceInstance} from "../../../models/serviceInstance";
import {VfModuleMap} from "../../../models/vfModulesMap";
@@ -145,6 +145,26 @@ export function vfModuleReducer(state: ServiceState , action: Action) : ServiceS
}
return clonedState;
}
+ case VfModuleActions.UPDATE_VFMODULE_FEILD : {
+ let clonedState = _.cloneDeep(state);
+ let updateFieldAction = <UpdateVFModuleField> action;
+
+ clonedState.serviceInstance[updateFieldAction.serviceId]
+ .vnfs[updateFieldAction.vnfStoreKey]
+ .vfModules[updateFieldAction.modelName][updateFieldAction.dynamicModelName][updateFieldAction.fieldName] = updateFieldAction.fieldValue;
+
+ return clonedState;
+ }
+ case VfModuleActions.DELETE_VFMODULE_FEILD : {
+ let clonedState = _.cloneDeep(state);
+ let deleteAction = <DeleteVFModuleField> action;
+
+ delete clonedState.serviceInstance[deleteAction.serviceId]
+ .vnfs[deleteAction.vnfStoreKey]
+ .vfModules[deleteAction.modelName][deleteAction.dynamicModelName][deleteAction.deleteFieldName];
+
+ return clonedState;
+ }
}
}
diff --git a/vid-webpack-master/src/app/shared/utils/constants.ts b/vid-webpack-master/src/app/shared/utils/constants.ts
index 400a4d8dc..f793e05db 100644
--- a/vid-webpack-master/src/app/shared/utils/constants.ts
+++ b/vid-webpack-master/src/app/shared/utils/constants.ts
@@ -92,7 +92,9 @@ export module Constants {
public static WELCOME_PATH = 'welcome.htm';
public static IS_PERMITTED_SUB_PATH = '&isPermitted=';
public static SERVICES_JOB_INFO_PATH = '../../asyncInstantiation';
+ public static SERVICE_MODEL_ID = 'serviceModelId';
public static SERVICES_RETRY_TOPOLOGY = '../../asyncInstantiation/bulkForRetry';
+ public static INSTANTIATION_TEMPLATE_TOPOLOGY = '../../asyncInstantiation/templateTopology';
public static CONFIGURATION_PATH = '../../get_property/{name}/defaultvalue';
public static SERVICES_JOB_AUDIT_PATH = '/auditStatus';
public static SERVICES_PROBE_PATH = "../../probe";
@@ -295,4 +297,8 @@ export module Constants {
export class LegacyRegion {
public static MEGA_REGION = ['AAIAIC25'];
}
+
+ export class ModelInfo {
+ public static UNLIMITED_DEFAULT = 'Unlimited (default)';
+ }
}
diff --git a/vid-webpack-master/src/app/shared/utils/util.spec.ts b/vid-webpack-master/src/app/shared/utils/util.spec.ts
index 2f9142f9c..ae39238c2 100644
--- a/vid-webpack-master/src/app/shared/utils/util.spec.ts
+++ b/vid-webpack-master/src/app/shared/utils/util.spec.ts
@@ -1,23 +1,8 @@
import {Utils} from "./utils";
-import {TestBed} from "@angular/core/testing";
+import each from "jest-each";
describe('Util', () => {
- let util: Utils;
-
- beforeAll(done => (async () => {
- TestBed.configureTestingModule({
-
- });
- await TestBed.compileComponents();
-
- util = new Utils();
-
- })().then(done).catch(done.fail));
-
- test('should be defined', () => {
- expect(util).toBeDefined();
- });
test('hasContents should return false if object is undefined or null or empty', () => {
expect(Utils.hasContents(undefined)).toBeFalsy();
@@ -28,4 +13,39 @@ describe('Util', () => {
test('hasContents should return true if object is not undefined and not null and not empty', () => {
expect(Utils.hasContents("someValue")).toBeTruthy();
});
+
+ const instantiationTypesDataProvider = [
+ ['Macro', false ],
+ ['ALaCarte', true ],
+ ['ClientConfig', true],
+ ['dont know', true]
+ ];
+ each(instantiationTypesDataProvider).test('instantiationType %s isALaCarte shall be %s', (instantiationType, expected ) => {
+ expect(Utils.isALaCarte(instantiationType)).toEqual(expected);
+ });
+
+ each([
+ ["empty properties, empty flags",{}, {}, 1],
+ ["null properties, undefined flags",null, undefined, 1],
+ ["max_instances 3, flag is on", {max_instances:3}, {FLAG_2002_UNLIMITED_MAX: true}, 3],
+ ["max_instances 3, flag is off", {max_instances:3}, {FLAG_2002_UNLIMITED_MAX: false}, 3],
+ ["null properties, flag is on", null, {FLAG_2002_UNLIMITED_MAX: true}, null],
+ ["null properties, flag is off", null, {FLAG_2002_UNLIMITED_MAX: false}, 1],
+ ["undefined properties, flag is off", undefined, {FLAG_2002_UNLIMITED_MAX: false}, 1],
+ ]).test('getMaxFirstLevel %s', (desc, properties, flags, expected) => {
+ expect(Utils.getMaxFirstLevel(properties, flags)).toEqual(expected);
+ });
+
+ each([
+ ["empty properties, empty flags",{}, {}, 1],
+ ["null properties, undefined flags",null, undefined, 1],
+ ["wrong field, flag is on", {max_instances:3}, {FLAG_2002_UNLIMITED_MAX: true}, null],
+ ["maxCountInstances 3, flag is on", {maxCountInstances:3}, {FLAG_2002_UNLIMITED_MAX: true}, 3],
+ ["maxCountInstances 3, flag is off", {maxCountInstances:3}, {FLAG_2002_UNLIMITED_MAX: true}, 3],
+ ]).test('getMaxFirstLevel %s', (desc, properties, flags, expected) => {
+ expect(Utils.getMaxVfModule(properties, flags)).toEqual(expected);
+ });
+
+
+
});
diff --git a/vid-webpack-master/src/app/shared/utils/utils.ts b/vid-webpack-master/src/app/shared/utils/utils.ts
index d63a3c997..3db770738 100644
--- a/vid-webpack-master/src/app/shared/utils/utils.ts
+++ b/vid-webpack-master/src/app/shared/utils/utils.ts
@@ -2,6 +2,21 @@ import * as _ from 'lodash'
export class Utils {
+ static getMaxFirstLevel(properties, flags: { [key: string]: boolean }) : number | null{
+ return this.getMaxInstancesAllowed(properties, 'max_instances', flags)
+ }
+
+ static getMaxVfModule(properties, flags: { [key: string]: boolean }) : number | null{
+ return this.getMaxInstancesAllowed(properties, 'maxCountInstances', flags)
+ }
+
+ static getMaxInstancesAllowed(properties, filedName: string, flags: { [key: string]: boolean }) : number | null{
+ if (!_.isNil(properties) && !_.isNil(properties[filedName])) {
+ return properties[filedName];
+ }
+ return (flags && !!flags['FLAG_2002_UNLIMITED_MAX']) ? null : 1;
+ }
+
public static clampNumber = (number, min, max) => {
return Math.max(min, Math.min(number, max));
};
@@ -179,6 +194,10 @@ export class Utils {
return (convertedAsdcModel);
};
+ public static isALaCarte(instantiationType) {
+ return instantiationType !== 'Macro';
+ }
+
private static convertOldModel(serviceModel ) {
let resource = {};
let convertedAsdcModel = {