Merge "Modify code to take care of missing scenario in US 832"
[vid.git] / vid-webpack-master / src / app / shared / components / genericForm / formControlsServices / vfModuleGenerator / vfModule.control.generator.ts
1 import {Injectable} from "@angular/core";
2 import {GenericFormService} from "../../generic-form.service";
3 import {AaiService} from "../../../../services/aaiService/aai.service";
4 import {NgRedux} from "@angular-redux/store";
5 import {HttpClient} from "@angular/common/http";
6 import {BasicControlGenerator} from "../basic.control.generator";
7 import * as _ from 'lodash';
8 import {Observable, of} from "rxjs";
9
10 import {
11   CustomValidatorOptions,
12   FormControlModel,
13   ValidatorModel,
14   ValidatorOptions
15 } from "../../../../models/formControlModels/formControl.model";
16 import {LogService} from "../../../../utils/log/log.service";
17 import {AppState} from "../../../../store/reducers";
18 import {FormGroup} from "@angular/forms";
19 import {DropdownFormControl} from "../../../../models/formControlModels/dropdownFormControl.model";
20 import {FormControlType} from "../../../../models/formControlModels/formControlTypes.enum";
21 import {InputFormControl} from "../../../../models/formControlModels/inputFormControl.model";
22 import {SelectOption} from "../../../../models/selectOption";
23 import {VfModuleInstance} from "../../../../models/vfModuleInstance";
24 import {VfModule} from "../../../../models/vfModule";
25 import {VNFModel} from "../../../../models/vnfModel";
26 import {VnfInstance} from "../../../../models/vnfInstance";
27 import {FileFormControl} from "../../../../models/formControlModels/fileFormControl.model";
28 import {CheckboxFormControl} from "../../../../models/formControlModels/checkboxFormControl.model";
29 import {FileUnit} from "../../../formControls/component/file/fileUnit.enum";
30 import {Constants} from "../../../../utils/constants";
31
32
33 export enum FormControlNames {
34   INSTANCE_NAME = 'instanceName',
35   VOLUME_GROUP_NAME = 'volumeGroupName',
36   LCPCLOUD_REGION_ID = 'lcpCloudRegionId',
37   LEGACY_REGION = 'legacyRegion',
38   TENANT_ID = 'tenantId',
39   ROLLBACK_ON_FAILURE = 'rollbackOnFailure',
40   SDN_C_PRE_LOAD = 'sdncPreLoad',
41   SUPPLEMENTARY_FILE = 'supplementaryFile'
42 }
43
44
45 @Injectable()
46 export class VfModuleControlGenerator {
47   aaiService: AaiService;
48   vfModuleModel: VfModule;
49   isUpdateMode : boolean;
50
51   constructor(private genericFormService: GenericFormService,
52               private _basicControlGenerator: BasicControlGenerator,
53               private store: NgRedux<AppState>,
54               private http: HttpClient,
55               private _aaiService: AaiService,
56               private _logService: LogService) {
57     this.aaiService = _aaiService;
58   }
59
60   setVFModuleStoreKey = (serviceId: string, vfModuleUuid: string) => {
61       const vfModules = this.store.getState().service.serviceHierarchy[serviceId].vfModules;
62       const vfModulesKeys = Object.keys(vfModules);
63       for(let key of  vfModulesKeys){
64         if(vfModules[key].uuid === vfModuleUuid){
65           return;
66         }
67       }
68   };
69
70
71   getVfModuleInstance = (serviceId: string, vnfStoreKey: string, UUIDData: Object, isUpdateMode: boolean): VfModuleInstance => {
72     let vfModuleInstance: VfModuleInstance = null;
73     if (isUpdateMode && this.store.getState().service.serviceInstance[serviceId] &&
74       _.has(this.store.getState().service.serviceInstance[serviceId].vnfs, vnfStoreKey) &&
75       _.has(this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules, UUIDData['modelName'])) {
76        vfModuleInstance = Object.assign({},this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules[UUIDData['modelName']][UUIDData['vFModuleStoreKey']]);
77     }
78     return vfModuleInstance;
79   };
80
81   extractVfAccordingToVfModuleUuid(serviceId: string, UUIDData: Object): VfModule {
82     const vfModule = this.store.getState().service.serviceHierarchy[serviceId].vfModules[UUIDData['modelName']];
83     this.vfModuleModel = vfModule;
84     return vfModule;
85   }
86
87   getMacroFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData : Object, isUpdateMode: boolean): FormControlModel[] {
88     this.isUpdateMode = isUpdateMode;
89     this.extractVfAccordingToVfModuleUuid(serviceId, uuidData);
90     if (_.isNil(serviceId) || _.isNil(vnfStoreKey) || _.isNil(vfModuleStoreKey)) {
91       if(isUpdateMode){
92         this._logService.error('should provide serviceId, vfModuleStoreKey, vnfStoreKey', serviceId);
93         return [];
94       }
95     }
96
97     const vfModuleInstance = this.getVfModuleInstance(serviceId, vnfStoreKey, uuidData, isUpdateMode);
98     const vfModuleModel = this.vfModuleModel;
99     const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey];
100     const vnfModelName: string = vnf.originalName;
101     const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfModelName]);
102
103     let result: FormControlModel[] = [];
104
105     if (!_.isNil(vfModuleModel)) {
106       result = this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, false);
107     }
108     if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
109       let suppFileInput:FileFormControl = <FileFormControl>(this.getSupplementaryFile(vfModuleInstance));
110       result.push(suppFileInput);
111       result = result.concat(suppFileInput.hiddenFile);
112     }
113     return result;
114   }
115
116   pushInstanceAndVGToForm(result: FormControlModel[], vfModuleElement: any, serviceId: string, vnfModel: any, isALaCarte: boolean) :FormControlModel[]{
117     result.push(this.getInstanceName(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming));
118     if (this.vfModuleModel.volumeGroupAllowed) {
119       result.push(this.getVolumeGroupData(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming, isALaCarte));
120     }
121     return result;
122   }
123
124   getAlaCarteFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData : Object, isUpdateMode: boolean): FormControlModel[] {
125     this.isUpdateMode = isUpdateMode;
126     this.extractVfAccordingToVfModuleUuid(serviceId, uuidData);
127     if (_.isNil(serviceId) || _.isNil(vnfStoreKey) || _.isNil(vfModuleStoreKey)) {
128       if(isUpdateMode){
129         this._logService.error('should provide serviceId, vfModuleStoreKey, vnfStoreKey', serviceId);
130         return [];
131       }
132     }
133     const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey];
134     const vnfModelName: string = vnf.originalName;
135     const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfModelName]);
136
137     const vfModuleInstance = this.getVfModuleInstance(serviceId, vnfStoreKey, uuidData, isUpdateMode);
138     let result: FormControlModel[] = [];
139     this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, true);
140     result.push(this.getLcpRegionControl(serviceId, vfModuleInstance, result));
141     result.push(this._basicControlGenerator.getLegacyRegion(vfModuleInstance));
142     result.push(this.getTenantControl(serviceId, vfModuleInstance, result));
143     result.push(this.getRollbackOnFailureControl(vfModuleInstance, result));
144     result.push(this.getSDNCControl(vfModuleInstance, result));
145     if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
146       let suppFileInput:FileFormControl = <FileFormControl>(this.getSupplementaryFile(vfModuleInstance));
147       result.push(suppFileInput);
148       result = result.concat(suppFileInput.hiddenFile);
149     }
150     return result;
151
152   }
153
154   getInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): FormControlModel {
155     let formControlModel:FormControlModel = this._basicControlGenerator.getInstanceNameController(instance, serviceId, isEcompGeneratedNaming, this.vfModuleModel);
156     formControlModel.onBlur = (event, form : FormGroup) => {
157         if(!_.isNil(form.controls['volumeGroupName'])&& event.target.value.length > 0){
158           form.controls['volumeGroupName'].setValue(event.target.value + "_vol");
159         }
160       };
161
162     return formControlModel;
163   }
164
165   getDefaultVolumeGroupName(instance: any, isEcompGeneratedNaming: boolean): string {
166     if (isEcompGeneratedNaming) {
167       return null;
168     }
169     return this._basicControlGenerator.getDefaultInstanceName(instance, this.vfModuleModel) + "_vol";
170   }
171
172   getVolumeGroupData(instance: any, serviceId: string, isEcompGeneratedNaming: boolean, isALaCarte: boolean): FormControlModel {
173     let validations: ValidatorModel[] = [
174       new ValidatorModel(ValidatorOptions.pattern, 'Instance name may include only alphanumeric characters and underscore.', BasicControlGenerator.INSTANCE_NAME_REG_EX),
175       new ValidatorModel(CustomValidatorOptions.uniqueInstanceNameValidator, 'Volume Group instance name is already in use, please pick another name', [this.store, serviceId, instance && instance.volumeGroupName])
176     ];
177     // comment out because if not provided vid won't create VG
178     // if (!isEcompGeneratedNaming)  {
179     //   validations.push(new ValidatorModel(ValidatorOptions.required, 'is required'));
180     // }
181     return new InputFormControl({
182       controlName: 'volumeGroupName',
183       displayName: 'Volume Group Name',
184       dataTestId: 'volumeGroupName',
185       // placeHolder: (!isEcompGeneratedNaming) ? 'Volume Group Name' : 'Automatically generated when not provided',
186       validations: validations,
187       tooltip : 'When filled, VID will create a Volume Group by this name and associate with this module.\n' +
188                 'When empty, the module is created without a Volume Group.',
189       isVisible: this.shouldVGNameBeVisible(isEcompGeneratedNaming,isALaCarte),
190       value: this.getDefaultVolumeGroupName(instance, isEcompGeneratedNaming),
191       onKeypress: (event) => {
192         const pattern:RegExp = BasicControlGenerator.INSTANCE_NAME_REG_EX;
193         if (pattern) {
194           if (!pattern.test(event['key'])) {
195             event.preventDefault();
196           }
197         }
198         return event;
199       }
200     });
201   }
202
203   private shouldVGNameBeVisible(isEcompGeneratedNaming: boolean, isALaCarte: boolean) {
204     if((!isALaCarte && !isEcompGeneratedNaming) || isALaCarte){
205       return true;
206     }
207     return false;
208
209   }
210
211   getSupplementaryFile(instance: any): FormControlModel {
212     return new FileFormControl({
213       controlName: FormControlNames.SUPPLEMENTARY_FILE,
214       displayName: 'Supplementary Data File (JSON format)',
215       dataTestId: 'SupplementaryFile',
216       placeHolder: 'Choose file',
217       selectedFile:  !_.isNil(instance) ? instance.supplementaryFileName: null,
218       isVisible: true,
219       acceptedExtentions: "application/json",
220       hiddenFile : [new InputFormControl({
221         controlName: FormControlNames.SUPPLEMENTARY_FILE + "_hidden",
222         isVisible: false,
223         validations: [new ValidatorModel(CustomValidatorOptions.isFileTooBig, "File size exceeds 5MB.", [FileUnit.MB, 5])]
224       }),
225         new InputFormControl({
226           controlName: FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content",
227           isVisible: false,
228           validations: [new ValidatorModel(CustomValidatorOptions.isValidJson,
229             "File is invalid, please make sure a legal JSON file is uploaded using name:value pairs.",[]),
230             new ValidatorModel(CustomValidatorOptions.isStringContainTags,
231               "File is invalid, please remove tags <>.",[])],
232           value: !_.isNil(instance) ? (instance.supplementaryFile_hidden_content): null,
233         })
234       ],
235       onDelete : (form : FormGroup) => {
236         form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
237         form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
238       },
239       onChange : (files: FileList, form : FormGroup)  => {
240         if (files.length > 0) {
241           const file = files.item(0);
242           let reader = new FileReader();
243           reader.onload = function(event) {
244             form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content"].setValue(reader.result);
245             form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden"].setValue(file);
246           };
247           reader.readAsText(file);
248         }
249         else {
250           form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
251           form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
252         }
253       }
254     })
255   };
256
257   getTenantControl = (serviceId: string, instance: any, controls: FormControlModel[]): DropdownFormControl => {
258     const service = this.store.getState().service.serviceInstance[serviceId];
259     const globalCustomerId: string = service.globalSubscriberId;
260     const serviceType: string = service.subscriptionServiceType;
261     return new DropdownFormControl({
262       type: FormControlType.DROPDOWN,
263       controlName: FormControlNames.TENANT_ID,
264       displayName: 'Tenant',
265       dataTestId: 'tenant',
266       placeHolder: 'Select Tenant',
267       name: "tenant",
268       isDisabled: _.isNil(instance) || _.isNil(instance.lcpCloudRegionId),
269       onInitSelectedField: instance ? ['lcpRegionsTenantsMap', instance.lcpCloudRegionId] : null,
270       value: instance ? instance.tenantId : null,
271       validations: [new ValidatorModel(ValidatorOptions.required, 'is required')],
272       onInit: instance ? this._basicControlGenerator.getSubscribeInitResult.bind(
273         this._aaiService,
274         this.aaiService.getLcpRegionsAndTenants.bind(this, globalCustomerId, serviceType)) : () => {
275       },
276     })
277   };
278
279   getLcpRegionControl = (serviceId: string, instance: any, controls: FormControlModel[]): DropdownFormControl => {
280     const service = this.store.getState().service.serviceInstance[serviceId];
281     const globalCustomerId: string = service.globalSubscriberId;
282     const serviceType: string = service.subscriptionServiceType;
283     return new DropdownFormControl({
284       type: FormControlType.DROPDOWN,
285       controlName: 'lcpCloudRegionId',
286       displayName: 'LCP region',
287       dataTestId: 'lcpRegion',
288       placeHolder: 'Select LCP Region',
289       name: "lcpRegion",
290       isDisabled: false,
291       value: instance ? instance.lcpCloudRegionId : null,
292       validations: [new ValidatorModel(ValidatorOptions.required, 'is required')],
293       onInitSelectedField: ['lcpRegionList'],
294       onInit: this._basicControlGenerator.getSubscribeInitResult.bind(
295         this._aaiService,
296         this._aaiService.getLcpRegionsAndTenants.bind(this, globalCustomerId, serviceType)),
297       onChange: (param: string, form: FormGroup) => {
298         form.controls[FormControlNames.TENANT_ID].enable();
299         form.controls[FormControlNames.TENANT_ID].reset();
300         if (!_.isNil(globalCustomerId) && !_.isNil(serviceType)) {
301           this._basicControlGenerator.getSubscribeResult.bind(this, this._aaiService.getLcpRegionsAndTenants(globalCustomerId, serviceType).subscribe(res => {
302             controls.find(item => item.controlName === FormControlNames.TENANT_ID)['options$'] = res.lcpRegionsTenantsMap[param];
303             if (res.lcpRegionsTenantsMap[param]) {
304               controls.find(item => item.controlName === FormControlNames.TENANT_ID)['hasEmptyOptions'] = res.lcpRegionsTenantsMap[param].length === 0;
305             }
306           }));
307         }
308
309         if (Constants.LegacyRegion.MEGA_REGION.indexOf(param) !== -1) {
310           form.controls['legacyRegion'].enable();
311           controls.find(item => item.controlName === 'legacyRegion').isVisible = true;
312
313         } else {
314           controls.find(item => item.controlName === 'legacyRegion').isVisible = false;
315           form.controls['legacyRegion'].setValue(null);
316           form.controls['legacyRegion'].reset();
317           form.controls['legacyRegion'].disable();
318         }
319       }
320     })
321   };
322
323   getSDNCControl = (instance: any, controls: FormControlModel[]): CheckboxFormControl => {
324     return new CheckboxFormControl({
325       type: FormControlType.CHECKBOX,
326       controlName: 'sdncPreLoad',
327       displayName: 'SDN-C pre-load',
328       dataTestId: 'sdncPreLoad',
329       value: instance ? instance.sdncPreLoad : false,
330       validations: [new ValidatorModel(ValidatorOptions.required, 'is required')]
331     })
332   };
333
334   getRollbackOnFailureControl = (instance: any, controls: FormControlModel[]): DropdownFormControl => {
335     return new DropdownFormControl({
336       type: FormControlType.DROPDOWN,
337       controlName: FormControlNames.ROLLBACK_ON_FAILURE,
338       displayName: 'Rollback on failure',
339       dataTestId: 'rollback',
340       isDisabled: false,
341       validations: [new ValidatorModel(ValidatorOptions.required, 'is required')],
342       value: instance ? instance.rollbackOnFailure : 'true',
343       onInit: this._basicControlGenerator.getSubscribeInitResult.bind(null, this.getRollBackOnFailureOptions)
344     })
345   };
346
347   getRollBackOnFailureOptions = (): Observable<SelectOption[]> => {
348     return of([
349       new SelectOption({id: 'true', name: 'Rollback'}),
350       new SelectOption({id: 'false', name: 'Don\'t Rollback'})
351     ]);
352   };
353 }