Fix for VID-928: NullPointerException during deploy service instance with empty cds...
[vid.git] / vid-webpack-master / src / app / shared / components / genericForm / formControlsServices / control.generator.util.service.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 {DynamicInputLabelPipe} from "../../../pipes/dynamicInputLabel/dynamic-input-label.pipe";
18 import {FormGeneralErrorsService} from "../../formGeneralErrors/formGeneralErrors.service";
19 import {Observable, of} from "rxjs";
20 import {NodeModel} from "../../../models/nodeModel";
21 import {Constants} from "../../../utils/constants";
22 import {FileUnit} from "../../formControls/component/file/fileUnit.enum";
23 import * as _ from 'lodash';
24
25 export const SUPPLEMENTARY_FILE = 'supplementaryFile';
26 export const SDN_C_PRE_LOAD = 'sdncPreLoad';
27 export const PAUSE_INSTANTIATION = 'pauseInstantiation';
28
29 @Injectable()
30 export class ControlGeneratorUtil {
31
32   public static readonly INSTANCE_NAME_REG_EX: RegExp = /^[a-zA-Z0-9._-]*$/;
33   public static readonly GENERATED_NAME_REG_EX: RegExp = /[^a-zA-Z0-9._-]/g;
34
35   constructor(private _store: NgRedux<AppState>) {
36   }
37
38   getSubscribeResult(subscribeFunction: Function, control: DropdownFormControl): Observable<any> {
39     return subscribeFunction(this).subscribe((res) => {
40       control.options$ = res;
41       control.hasEmptyOptions = res.length === 0;
42       FormGeneralErrorsService.checkForErrorTrigger.next();
43       return of(res);
44     });
45   }
46
47   getSubscribeInitResult(subscribeFunction: Function, control: DropdownFormControl, form: FormGroup): Observable<any> {
48     return subscribeFunction(this).subscribe((res) => {
49       if (!_.isNil(control['onInitSelectedField'])) {
50         let result = res;
51         for (let key of control['onInitSelectedField']) {
52           result = !_.isNil(result[key]) ? result[key] : [];
53         }
54         control.options$ = result;
55         control.hasEmptyOptions = _.isNil(result) || result.length === 0;
56       } else {
57         control.options$ = !_.isNil(res) ? res : [];
58         control.hasEmptyOptions = _.isNil(res) || res.length === 0;
59       }
60
61       FormGeneralErrorsService.checkForErrorTrigger.next();
62       return of(res);
63     });
64   }
65
66   isLegacyRegionShouldBeVisible(instance: any): boolean {
67     if (!_.isNil(instance) && !_.isNil(instance.lcpCloudRegionId)) {
68       return Constants.LegacyRegion.MEGA_REGION.indexOf(instance.lcpCloudRegionId) !== -1;
69     }
70     return false;
71   }
72
73   createValidationsForInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): ValidatorModel[] {
74     let validations: ValidatorModel[] = [
75       new ValidatorModel(ValidatorOptions.pattern, 'Instance name may include only alphanumeric characters and underscore.', ControlGeneratorUtil.INSTANCE_NAME_REG_EX),
76       new ValidatorModel(CustomValidatorOptions.uniqueInstanceNameValidator, 'some error', [this._store, serviceId, instance && instance.instanceName])
77     ];
78     if (!isEcompGeneratedNaming) {
79       validations.push(new ValidatorModel(ValidatorOptions.required, 'is required'));
80     }
81     return validations;
82   }
83
84   getInputsOptions = (options: any[]): Observable<SelectOption[]> => {
85     let optionList: SelectOption[] = [];
86     options.forEach((option) => {
87       optionList.push(new SelectOption({
88         id: option.id || option.name,
89         name: option.name
90       }));
91     });
92     return of(optionList);
93   };
94
95   getDynamicInputsByType(dynamicInputs: any, serviceModelId: string, storeKey: string, type: string): FormControlModel[] {
96     let result: FormControlModel[] = [];
97     if (dynamicInputs) {
98       let nodeInstance = null;
99       if (_.has(this._store.getState().service.serviceInstance[serviceModelId][type], storeKey)) {
100         nodeInstance = Object.assign({}, this._store.getState().service.serviceInstance[serviceModelId][type][storeKey]);
101       }
102       result = this.getDynamicInputs(dynamicInputs, nodeInstance);
103     }
104     return result;
105   }
106
107   getServiceDynamicInputs(dynamicInputs: any, serviceModelId: string): FormControlModel[] {
108     let result: FormControlModel[] = [];
109     if (dynamicInputs) {
110       let serviceInstance = null;
111       if (_.has(this._store.getState().service.serviceInstance, serviceModelId)) {
112         serviceInstance = Object.assign({}, this._store.getState().service.serviceInstance[serviceModelId]);
113       }
114       result = this.getDynamicInputs(dynamicInputs, serviceInstance);
115     }
116     return result;
117   }
118
119   getDynamicInputs(dynamicInputs: any, instance: any): FormControlModel[] {
120     let result: FormControlModel[] = [];
121     if (dynamicInputs) {
122       dynamicInputs.forEach((input) => {
123         let validations: ValidatorModel[] = [];
124         if (input.isRequired) {
125           validations.push(new ValidatorModel(ValidatorOptions.required, 'is required'))
126         }
127         if (input.minLength) {
128           validations.push(new ValidatorModel(ValidatorOptions.minLength, '', input.minLength))
129         }
130         if (input.maxLength) {
131           validations.push(new ValidatorModel(ValidatorOptions.maxLength, '', input.maxLength))
132         }
133
134         let dynamicInputLabelPipe: DynamicInputLabelPipe = new DynamicInputLabelPipe();
135         let data: any = {
136           controlName: input.name,
137           displayName: dynamicInputLabelPipe.transform(input.name).slice(0, -1),
138           dataTestId: input.id,
139           placeHolder: input.prompt,
140           tooltip: input.description,
141           validations: validations,
142           isVisible: input.isVisible,
143           value: !_.isNil(instance) && !_.isNil(instance.instanceParams) && instance.instanceParams.length > 0 ? instance.instanceParams[0][input.name] : input.value
144         };
145
146         switch (input.type) {
147           case 'select' :
148           case 'boolean' : {
149             data.value = data.value || input.optionList.filter((option) => option.isDefault ? option.id || option.name : null);
150             data.onInit = this.getSubscribeInitResult.bind(null, input.optionList == null ? this.getBooleanOptions : this.getInputsOptions.bind(this, input.optionList));
151             result.push(new DropdownFormControl(data));
152             break;
153           }
154           case 'checkbox': {
155             data.type = FormControlType.CHECKBOX;
156             result.push(new FormControlModel(data));
157             break;
158           }
159           case 'number': {
160             data.min = input.min;
161             data.max = input.max;
162             result.push(new NumberFormControl(data));
163             break;
164           }
165           case 'file': {
166             result.push(new FileFormControl(data));
167             break;
168           }
169           default: {
170             result.push(new InputFormControl(data));
171           }
172         }
173       })
174     }
175
176     return result;
177   }
178
179   getDefaultInstanceName(instance: any, model: NodeModel): string {
180     const initialInstanceName = (!_.isNil(instance) && instance.instanceName) || (!_.isNil(model.name) ? model.name.replace(ControlGeneratorUtil.GENERATED_NAME_REG_EX, "") : model.name);
181     return initialInstanceName;
182   }
183
184   concatSupplementaryFile(originalArray: FormControlModel[], vfModuleInstance): FormControlModel[] {
185     let suppFileInput: FileFormControl = <FileFormControl>(this.getSupplementaryFile(vfModuleInstance));
186     return originalArray.concat([suppFileInput], suppFileInput.hiddenFile);
187   }
188
189   getSupplementaryFile(instance: any): FileFormControl {
190     return new FileFormControl({
191       controlName: SUPPLEMENTARY_FILE,
192       displayName: 'Supplementary Data File (JSON format)',
193       dataTestId: 'SupplementaryFile',
194       placeHolder: 'Choose file',
195       selectedFile: !_.isNil(instance) ? instance.supplementaryFileName : null,
196       isVisible: true,
197       acceptedExtentions: "application/json",
198       hiddenFile: [new InputFormControl({
199         controlName: SUPPLEMENTARY_FILE + "_hidden",
200         isVisible: false,
201         validations: [new ValidatorModel(CustomValidatorOptions.isFileTooBig, "File size exceeds 5MB.", [FileUnit.MB, 5])]
202       }),
203         new InputFormControl({
204           controlName: SUPPLEMENTARY_FILE + "_hidden_content",
205           isVisible: false,
206           validations: [new ValidatorModel(CustomValidatorOptions.isValidJson,
207             "File is invalid, please make sure a legal JSON file is uploaded using name:value pairs.", []),
208             new ValidatorModel(CustomValidatorOptions.isStringContainTags,
209               "File is invalid, please remove tags <>.", [])],
210           value: !_.isNil(instance) ? (instance.supplementaryFile_hidden_content) : null,
211         })
212       ],
213       onDelete: this.getOnDeleteForSupplementaryFile(),
214       onChange: this.getOnChangeForSupplementaryFile()
215     })
216   };
217
218   retrieveInstanceIfUpdateMode(store: NgRedux<AppState>, instance: any): any {
219     return store.getState().global.isUpdateModalMode ? instance : null;
220   }
221
222   private getOnDeleteForSupplementaryFile() {
223     return (form: FormGroup) => {
224       form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
225       form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
226     };
227   }
228
229   private getOnChangeForSupplementaryFile() {
230     return (files: FileList, form: FormGroup) => {
231       if (files.length > 0) {
232         const file = files.item(0);
233         let reader = new FileReader();
234         reader.onload = function (event) {
235           form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(reader.result);
236           form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(file);
237         };
238         reader.readAsText(file);
239       } else {
240         form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(null);
241         form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null);
242       }
243     };
244   }
245
246   getRollBackOnFailureOptions = (): Observable<SelectOption[]> => {
247     return of([
248       new SelectOption({id: 'true', name: 'Rollback'}),
249       new SelectOption({id: 'false', name: 'Don\'t Rollback'})
250     ]);
251   };
252
253   getBooleanOptions = (): Observable<SelectOption[]> => {
254     return of([
255       new SelectOption({id: 'true', name: 'true'}),
256       new SelectOption({id: 'false', name: 'false'})
257     ]);
258   };
259
260 }