Merge "Extract getSupplementaryFile out of VFM controller"
[vid.git] / vid-webpack-master / src / app / shared / components / genericForm / formControlsServices / basic.control.generator.ts
1 import {Injectable} from "@angular/core";
2 import {DropdownFormControl} from "../../../models/formControlModels/dropdownFormControl.model";
3 import {FormGroup} from "@angular/forms";
4 import {
5   CustomValidatorOptions,
6   FormControlModel,
7   ValidatorModel,
8   ValidatorOptions
9 } from "../../../models/formControlModels/formControl.model";
10 import {InputFormControl} from "../../../models/formControlModels/inputFormControl.model";
11 import {AppState} from "../../../store/reducers";
12 import {NgRedux} from "@angular-redux/store";
13 import {NumberFormControl} from "../../../models/formControlModels/numberFormControl.model";
14 import {FormControlType} from "../../../models/formControlModels/formControlTypes.enum";
15 import {FileFormControl} from "../../../models/formControlModels/fileFormControl.model";
16 import {SelectOption} from "../../../models/selectOption";
17 import * as _ from 'lodash';
18 import {DynamicInputLabelPipe} from "../../../pipes/dynamicInputLabel/dynamic-input-label.pipe";
19 import {AaiService} from "../../../services/aaiService/aai.service";
20 import {FormGeneralErrorsService} from "../../formGeneralErrors/formGeneralErrors.service";
21 import {Observable, of} from "rxjs";
22 import {NodeModel} from "../../../models/nodeModel";
23 import {Constants} from "../../../utils/constants";
24 import {FileUnit} from "../../formControls/component/file/fileUnit.enum";
25
26 const SUPPLEMENTARY_FILE = 'supplementaryFile';
27
28 @Injectable()
29 export class BasicControlGenerator {
30
31   public static readonly INSTANCE_NAME_REG_EX:RegExp = /^[a-zA-Z0-9._-]*$/;
32   public static readonly GENERATED_NAME_REG_EX:RegExp = /[^a-zA-Z0-9._-]/g;
33
34   constructor(private _store : NgRedux<AppState>,
35               private _aaiService : AaiService){}
36   getSubscribeResult(subscribeFunction : Function, control : DropdownFormControl) : Observable<any>{
37     return subscribeFunction(this).subscribe((res) => {
38       control.options$ = res;
39       control.hasEmptyOptions = res.length === 0;
40       FormGeneralErrorsService.checkForErrorTrigger.next();
41       return of(res);
42     });
43   }
44
45   getSubscribeInitResult(subscribeFunction : Function, control : DropdownFormControl, form : FormGroup) : Observable<any>{
46     return subscribeFunction(this).subscribe((res) => {
47       if(!_.isNil(control['onInitSelectedField'])){
48         let result = res;
49         for(let key of control['onInitSelectedField']){
50           result = !_.isNil(result[key]) ? result[key] : [];
51         }
52         control.options$ = result;
53         control.hasEmptyOptions = _.isNil(result) || result.length === 0;
54       } else{
55         control.options$ = !_.isNil(res) ? res : [];
56         control.hasEmptyOptions = _.isNil(res) || res.length === 0;
57       }
58
59       FormGeneralErrorsService.checkForErrorTrigger.next();
60       return of(res);
61     });
62   }
63
64   getInstanceNameController(instance: any, serviceId: string, isEcompGeneratedNaming: boolean, model: NodeModel): FormControlModel {
65     let validations: ValidatorModel[] = this.createValidationsForInstanceName(instance, serviceId, isEcompGeneratedNaming);
66     return new InputFormControl({
67       controlName: 'instanceName',
68       displayName: 'Instance name',
69       dataTestId: 'instanceName',
70       placeHolder: (!isEcompGeneratedNaming) ? 'Instance name' : 'Automatically generated when not provided',
71       validations: validations,
72       isVisible : true,
73       value : (!isEcompGeneratedNaming || (!_.isNil(instance) && !_.isNil(instance.instanceName)))
74         ? this.getDefaultInstanceName(instance, model) : null,
75       onKeypress : (event) => {
76         const pattern:RegExp = BasicControlGenerator.INSTANCE_NAME_REG_EX;
77         if(pattern){
78           if(!pattern.test(event['key'])){
79             event.preventDefault();
80           }
81         }
82         return event;
83       }
84     });
85   }
86
87   getInstanceName(instance : any, serviceId : string, isEcompGeneratedNaming: boolean): FormControlModel {
88     let formControlModel:FormControlModel = this.getInstanceNameController(instance, serviceId, isEcompGeneratedNaming, new NodeModel());
89     formControlModel.value = instance ? instance.instanceName : null;
90     return formControlModel;
91   }
92
93   isLegacyRegionShouldBeVisible(instance : any) : boolean {
94     if(!_.isNil(instance) && !_.isNil(instance.lcpCloudRegionId))  {
95       return Constants.LegacyRegion.MEGA_REGION.indexOf(instance.lcpCloudRegionId) !== -1;
96     }
97     return false;
98   }
99
100   getLegacyRegion(instance: any): FormControlModel {
101     return new InputFormControl({
102       controlName: 'legacyRegion',
103       displayName: 'Legacy Region',
104       dataTestId: 'lcpRegionText',
105       placeHolder: 'Type Legacy Region',
106       validations: [],
107       isVisible: this.isLegacyRegionShouldBeVisible(instance),
108       isDisabled : _.isNil(instance) ? true : Constants.LegacyRegion.MEGA_REGION.indexOf(instance.lcpCloudRegionId),
109       value: instance ? instance.legacyRegion : null
110     });
111   }
112
113   private createValidationsForInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): ValidatorModel[] {
114     let validations: ValidatorModel[] = [
115       new ValidatorModel(ValidatorOptions.pattern, 'Instance name may include only alphanumeric characters and underscore.', BasicControlGenerator.INSTANCE_NAME_REG_EX),
116       new ValidatorModel(CustomValidatorOptions.uniqueInstanceNameValidator, 'some error', [this._store, serviceId, instance && instance.instanceName])
117     ];
118     if (!isEcompGeneratedNaming) {
119       validations.push(new ValidatorModel(ValidatorOptions.required, 'is required'));
120     }
121     return validations;
122   }
123
124   getInputsOptions = (options: any[]) : Observable<SelectOption[]> =>{
125     let optionList: SelectOption[] = [];
126     options.forEach((option) => {
127       optionList.push(new SelectOption({
128         id: option.id || option.name,
129         name: option.name
130       }));
131     });
132     return of(optionList);
133   };
134
135   getProductFamilyControl = (instance : any, controls : FormControlModel[], isMandatory?: boolean) : DropdownFormControl => {
136     return new DropdownFormControl({
137       type : FormControlType.DROPDOWN,
138       controlName : 'productFamilyId',
139       displayName : 'Product family',
140       dataTestId : 'productFamily',
141       placeHolder : 'Select Product Family',
142       isDisabled : false,
143       name : "product-family-select",
144       value : instance ? instance.productFamilyId : null,
145       validations : _.isNil(isMandatory) || isMandatory === true ? [new ValidatorModel(ValidatorOptions.required, 'is required')]: [],
146       onInit : this.getSubscribeResult.bind(this, this._aaiService.getProductFamilies),
147     })
148   };
149
150
151
152   getDynamicInputsByType(dynamicInputs : any, serviceModelId : string, storeKey : string, type: string ) : FormControlModel[] {
153     let result : FormControlModel[] = [];
154     if(dynamicInputs) {
155       let nodeInstance = null;
156       if (_.has(this._store.getState().service.serviceInstance[serviceModelId][type], storeKey)) {
157         nodeInstance = Object.assign({}, this._store.getState().service.serviceInstance[serviceModelId][type][storeKey]);
158       }
159       result = this.getDynamicInputs(dynamicInputs, nodeInstance);
160     }
161     return result;
162   }
163
164
165   getServiceDynamicInputs(dynamicInputs : any, serviceModelId : string) : FormControlModel[] {
166     let result: FormControlModel[] = [];
167     if (dynamicInputs) {
168       let serviceInstance = null;
169       if (_.has(this._store.getState().service.serviceInstance, serviceModelId)) {
170         serviceInstance = Object.assign({}, this._store.getState().service.serviceInstance[serviceModelId]);
171       }
172       result = this.getDynamicInputs(dynamicInputs, serviceInstance);
173     }
174     return result;
175   }
176
177   getDynamicInputs(dynamicInputs : any, instance :any)  : FormControlModel[]{
178     let result : FormControlModel[] = [];
179     if(dynamicInputs) {
180       dynamicInputs.forEach((input)=> {
181         let validations: ValidatorModel[] = [];
182         if(input.isRequired) {
183           validations.push(new ValidatorModel(ValidatorOptions.required, 'is required'))
184         }
185         if(input.minLength) {
186           validations.push(new ValidatorModel(ValidatorOptions.minLength, '', input.minLength))
187         }
188         if(input.maxLength) {
189           validations.push(new ValidatorModel(ValidatorOptions.maxLength, '', input.maxLength))
190         }
191
192         let dynamicInputLabelPipe: DynamicInputLabelPipe = new DynamicInputLabelPipe();
193         let data:any = {
194           controlName: input.name,
195           displayName: dynamicInputLabelPipe.transform(input.name).slice(0, -1),
196           dataTestId: input.id,
197           placeHolder: input.prompt,
198           tooltip: input.description,
199           validations: validations,
200           isVisible: input.isVisible,
201           value: !_.isNil(instance) && !_.isNil(instance.instanceParams) && instance.instanceParams.length > 0 ? instance.instanceParams[0][input.name] : input.value
202         };
203
204         switch (input.type) {
205           case 'select' :
206           case 'boolean' :{
207             data.value = data.value || input.optionList.filter((option) => option.isDefault ? option.id || option.name: null);
208             data.onInit  = this.getSubscribeInitResult.bind(null, this.getInputsOptions.bind(this, input.optionList));
209             result.push(new DropdownFormControl(data));
210             break;
211           }
212           case 'checkbox': {
213             data.type = FormControlType.CHECKBOX;
214             result.push(new FormControlModel(data));
215             break;
216           }
217           case 'number': {
218             data.min = input.min;
219             data.max = input.max;
220             result.push(new NumberFormControl(data));
221             break;
222           }
223           case 'file': {
224             result.push(new FileFormControl(data));
225             break;
226           }
227           default: {
228             result.push(new InputFormControl(data));
229           }
230         }
231       })
232     }
233
234     return result;
235   }
236
237   getDefaultInstanceName(instance: any, model: NodeModel) : string {
238     const initialInstanceName = (!_.isNil(instance) && instance.instanceName) || (!_.isNil(model.name) ? model.name.replace(BasicControlGenerator.GENERATED_NAME_REG_EX, "") : model.name);
239     return initialInstanceName;
240   }
241
242   getSupplementaryFile(instance: any): FileFormControl {
243     return new FileFormControl({
244       controlName: SUPPLEMENTARY_FILE,
245       displayName: 'Supplementary Data File (JSON format)',
246       dataTestId: 'SupplementaryFile',
247       placeHolder: 'Choose file',
248       selectedFile:  !_.isNil(instance) ? instance.supplementaryFileName: null,
249       isVisible: true,
250       acceptedExtentions: "application/json",
251       hiddenFile : [new InputFormControl({
252         controlName: SUPPLEMENTARY_FILE + "_hidden",
253         isVisible: false,
254         validations: [new ValidatorModel(CustomValidatorOptions.isFileTooBig, "File size exceeds 5MB.", [FileUnit.MB, 5])]
255       }),
256         new InputFormControl({
257           controlName: SUPPLEMENTARY_FILE + "_hidden_content",
258           isVisible: false,
259           validations: [new ValidatorModel(CustomValidatorOptions.isValidJson,
260             "File is invalid, please make sure a legal JSON file is uploaded using name:value pairs.",[]),
261             new ValidatorModel(CustomValidatorOptions.isStringContainTags,
262               "File is invalid, please remove tags <>.",[])],
263           value: !_.isNil(instance) ? (instance.supplementaryFile_hidden_content): null,
264         })
265       ],
266       onDelete : this.getOnDeleteForSupplementaryFile(),
267       onChange : this.getOnChangeForSupplementaryFile()
268     })
269   };
270
271   private getOnDeleteForSupplementaryFile() {
272     return (form: FormGroup) => {
273       form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
274       form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
275     };
276   }
277
278   private getOnChangeForSupplementaryFile() {
279     return (files: FileList, form: FormGroup) => {
280       if (files.length > 0) {
281         const file = files.item(0);
282         let reader = new FileReader();
283         reader.onload = function (event) {
284           form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(reader.result);
285           form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(file);
286         };
287         reader.readAsText(file);
288       } else {
289         form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
290         form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
291       }
292     };
293   }
294 }