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