Fix various bugs related to tosca custom functions
[sdc.git] / catalog-ui / src / app / ng2 / pages / properties-assignment / tosca-function / tosca-custom-function / tosca-custom-function.component.ts
1 /*
2  * -
3  *  ============LICENSE_START=======================================================
4  *  Copyright (C) 2023 Nordix Foundation.
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21
22 import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
23 import {FormArray, FormControl, FormGroup, Validators} from "@angular/forms";
24 import {ToscaCustomFunction} from "../../../../../models/tosca-custom-function";
25 import {ToscaFunctionParameter} from "../../../../../models/tosca-function-parameter";
26 import {ToscaStringParameter} from "../../../../../models/tosca-string-parameter";
27 import {ToscaFunctionType} from "../../../../../models/tosca-function-type.enum";
28 import {PropertyBEModel} from "../../../../../models/properties-inputs/property-be-model";
29 import {PROPERTY_TYPES} from "../../../../../utils/constants";
30 import {InstanceFeDetails} from "../../../../../models/instance-fe-details";
31 import {ToscaFunctionValidationEvent} from "../tosca-function.component";
32 import {ToscaFunction} from "../../../../../models/tosca-function";
33 import {ToscaGetFunction} from "../../../../../models/tosca-get-function";
34 import {CustomToscaFunction} from "../../../../../models/default-custom-functions";
35 import {ToscaGetFunctionValidationEvent} from "../tosca-get-function/tosca-get-function.component";
36
37 @Component({
38     selector: 'app-tosca-custom-function',
39     templateUrl: './tosca-custom-function.component.html',
40     styleUrls: ['./tosca-custom-function.component.less']
41 })
42 export class ToscaCustomFunctionComponent implements OnInit {
43
44     @Input() toscaCustomFunction: ToscaCustomFunction;
45     @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
46     @Input() customToscaFunctions: Array<CustomToscaFunction> = [];
47     @Input() name: string;
48     @Input() type: ToscaFunctionType;
49     @Input() propertyType: string;
50     @Input() propertySchemaType: string = undefined;
51     @Input() isDefaultCustomFunction: boolean;
52     @Output() onValidFunction: EventEmitter<ToscaCustomFunction> = new EventEmitter<ToscaCustomFunction>();
53     @Output() onValidityChange: EventEmitter<ToscaCustomFunctionValidationEvent> = new EventEmitter<ToscaCustomFunctionValidationEvent>();
54
55     toscaGetFunction: ToscaFunction;
56     customFunctionFormName: FormControl = new FormControl('', [Validators.required, Validators.minLength(1)]);
57     customParameterFormArray: FormArray = new FormArray([], Validators.minLength(1));
58     formGroup: FormGroup = new FormGroup(
59         {
60             'customParameterList': this.customParameterFormArray,
61             'customName': this.customFunctionFormName
62         }
63     );
64
65     parameters: ToscaFunctionParameter[] = [];
66     propertyInputList: Array<PropertyBEModel> = [];
67     previousType: ToscaFunctionType;
68
69     STRING_FUNCTION_TYPE = ToscaFunctionType.STRING;
70     GET_INPUT = ToscaFunctionType.GET_INPUT;
71
72     ngOnInit() {
73         this.initForm();
74     }
75
76     ngOnChanges() {
77         if (this.previousType && this.previousType != this.type) {
78             this.propertyInputList = [];
79             this.customParameterFormArray = new FormArray([], Validators.minLength(1));
80             this.parameters = [];
81         }
82         this.fillVariables();
83         if (this.name) {
84             this.customFunctionFormName.setValue(this.name);
85             this.emitOnValidityChange();
86         } else {
87             this.name = '';
88         }
89         this.previousType = this.type;
90     }
91
92     private initForm(): void {
93         this.formGroup.valueChanges.subscribe(() => {
94             this.emitOnValidityChange();
95             if (this.formGroup.valid) {
96                 this.onValidFunction.emit(this.buildCustomFunctionFromForm());
97             }
98         });
99     }
100
101     private fillVariables() {
102         if (!this.toscaCustomFunction) {
103             if (this.type === this.GET_INPUT && this.parameters.length < 1) {
104                 this.addFunction();
105             }
106             return;
107         }
108         if (this.toscaCustomFunction.parameters) {
109             this.name = this.toscaCustomFunction.name;
110             this.customFunctionFormName.setValue(this.name)
111             this.parameters = Array.from(this.toscaCustomFunction.parameters);
112             for (const parameter of this.parameters) {
113                 if (this.type === this.GET_INPUT) {
114                     this.toscaGetFunction = parameter as ToscaGetFunction;
115                     this.addToscaFunctionToParameters(parameter);
116                     return;
117                 }
118                 if (parameter.type !== PROPERTY_TYPES.STRING) {
119                     this.addToscaFunctionToParameters(parameter);
120                 } else {
121                     this.propertyInputList.push(undefined);
122                     this.customParameterFormArray.push(
123                         new FormControl(parameter.value, [Validators.required, Validators.minLength(1)])
124                     );
125                 }
126             }
127         }
128         if (this.type === this.GET_INPUT && this.parameters.length < 1) {
129             this.addFunction();
130         }
131     }
132
133     private addToscaFunctionToParameters(parameter: ToscaFunctionParameter) {
134         const propertyBEModel = this.createProperty(parameter.value);
135         propertyBEModel.toscaFunction = <ToscaFunction> parameter;
136         this.propertyInputList.push(propertyBEModel);
137         this.customParameterFormArray.push(
138             new FormControl(parameter, [Validators.required, Validators.minLength(1)])
139         );
140     }
141
142     private buildCustomFunctionFromForm(): ToscaCustomFunction {
143         const toscaCustomFunction1 = new ToscaCustomFunction();
144         toscaCustomFunction1.name = this.customFunctionFormName.value;
145         this.customParameterFormArray.controls.forEach(control => {
146             const value = control.value;
147             if (!value) {
148                 return;
149             }
150             if (typeof value === 'string') {
151                 const stringParameter = new ToscaStringParameter();
152                 stringParameter.value = value;
153                 toscaCustomFunction1.parameters.push(stringParameter);
154             } else {
155                 toscaCustomFunction1.parameters.push(control.value);
156             }
157         });
158
159         return toscaCustomFunction1;
160     }
161
162     private emitOnValidityChange() {
163         this.onValidityChange.emit({
164             isValid: this.formGroup.valid,
165             toscaCustomFunction: this.formGroup.valid ? this.buildCustomFunctionFromForm() : undefined
166         })
167     }
168
169     addFunction(): void {
170         this.propertyInputList.push(this.createProperty());
171         this.parameters.push({} as ToscaFunctionParameter);
172         this.customParameterFormArray.push(
173             new FormControl(undefined, [Validators.required, Validators.minLength(1)])
174         );
175     }
176
177     addStringParameter(): void {
178         const toscaStringParameter = new ToscaStringParameter();
179         toscaStringParameter.value = '';
180         this.propertyInputList.push(undefined);
181         this.customParameterFormArray.push(
182             new FormControl('', [Validators.required, Validators.minLength(1)])
183         );
184         this.parameters.push(toscaStringParameter);
185         console.log(this.customParameterFormArray)
186     }
187
188     removeParameter(position): void {
189         this.propertyInputList.splice(position, 1);
190         this.parameters.splice(position, 1);
191         this.customParameterFormArray.removeAt(position);
192     }
193
194     createProperty(value?: any): PropertyBEModel {
195         const property = new PropertyBEModel();
196         if (this.type === this.GET_INPUT) {
197             property.type = this.propertyType;
198             if (this.propertySchemaType) {
199                 property.schemaType = this.propertySchemaType;
200             }
201         } else {
202             property.type = PROPERTY_TYPES.ANY;
203         }
204         
205         property.value = value ? value : undefined;
206         return property;
207     }
208
209     onFunctionValidityChange(event: ToscaFunctionValidationEvent, index: number): void {
210         if (event.isValid && event.toscaFunction) {
211             this.customParameterFormArray.controls[index].setValue(event.toscaFunction)
212         } else {
213             this.customParameterFormArray.controls[index].setValue(undefined);
214         }
215     }
216
217     onGetFunctionValidityChange(event: ToscaGetFunctionValidationEvent, index: number): void {
218         if (event.isValid && event.toscaGetFunction) {
219             this.customParameterFormArray.controls[index].setValue(event.toscaGetFunction);
220         } else {
221             this.customParameterFormArray.controls[index].setValue(undefined);
222         }
223         this.emitOnValidityChange();
224     }
225 }
226
227 export interface ToscaCustomFunctionValidationEvent {
228     isValid: boolean,
229     toscaCustomFunction: ToscaCustomFunction,
230 }