Implement adding Interface to VFC
[sdc.git] / catalog-ui / src / app / ng2 / pages / interface-definition / operation-creator / param-row / param-row.component.ts
1 /*
2 * ============LICENSE_START=======================================================
3 * SDC
4 * ================================================================================
5 *  Copyright (C) 2022 Nordix Foundation. All rights reserved.
6 *  ================================================================================
7 *  Licensed under the Apache License, Version 2.0 (the "License");
8 *  you may not use this file except in compliance with the License.
9 *  You may obtain a copy of the License at
10 *
11 *        http://www.apache.org/licenses/LICENSE-2.0
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 import {Component, Input} from '@angular/core';
22 import {DataTypeService} from "app/ng2/services/data-type.service";
23 import {
24     Capability,
25     DataTypeModel,
26     InputBEModel,
27     OperationModel,
28     OperationParameter
29 } from 'app/models';
30 import {
31     DropdownValue
32 } from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
33 import {WorkspaceService} from "../../../workspace/workspace.service";
34
35 class DropdownValueType extends DropdownValue {
36     type: string;
37
38     constructor(value: string, label: string, type?: string) {
39         super(value, label);
40         if (type) {
41             this.type = type;
42         }
43     }
44 }
45
46 @Component({
47     selector: 'param-row',
48     templateUrl: './param-row.component.html',
49     styleUrls: ['./param-row.component.less']
50 })
51
52 export class ParamRowComponent {
53     @Input() param: OperationParameter;
54     @Input() inputProps: Array<InputBEModel>;
55     @Input() operationOutputs: Array<OperationModel>;
56     @Input() capabilitiesProps: Array<Capability>;
57     @Input() onRemoveParam: Function;
58     @Input() isAssociateWorkflow: boolean;
59     @Input() readonly: boolean;
60     @Input() isInputParam: boolean;
61     @Input() validityChanged: Function;
62
63     propTypeEnum: Array<string> = [];
64     operationOutputCats: Array<{ operationName: string, outputs: Array<DropdownValueType> }> = [];
65     filteredInputProps: Array<DropdownValue> = [];
66     filteredCapabilitiesProps: Array<{ capabilityName: string, properties: Array<DropdownValueType> }> = [];
67
68     constructor(private dataTypeService: DataTypeService, protected workspaceService: WorkspaceService) {
69     }
70
71     ngOnInit() {
72         if (this.isInputParam) {
73             this.propTypeEnum = _.uniq(
74                 _.map(
75                     _.concat(
76                         this.getPrimitiveSubtypes(),
77                         _.reduce(
78                             this.operationOutputs,
79                             (acc, op) => [...acc, ...op.outputs.listToscaDataDefinition],
80                             []),
81                         _.reduce(
82                             this.capabilitiesProps,
83                             (acc, capab) => [...acc, ...capab.properties],
84                             [])
85                     ),
86                     prop => prop.type
87                 )
88             );
89         } else {
90             const dataTypes: Array<DataTypeModel> = _.toArray(this.dataTypeService.getDataTypeByModel(this.workspaceService.metadata.model));
91             this.propTypeEnum = _.concat(
92                 _.map(
93                     _.filter(
94                         dataTypes,
95                         type => this.isTypePrimitive(type.name)
96                     ),
97                     type => type.name
98                 ).sort(),
99                 _.map(
100                     _.filter(
101                         dataTypes,
102                         type => !this.isTypePrimitive(type.name)
103                     ),
104                     type => type.name
105                 ).sort()
106             );
107         }
108
109         this.onChangeType();
110         this.validityChanged();
111     }
112
113     onChangeName() {
114         this.validityChanged();
115     }
116
117     onChangeType() {
118         if (!this.isInputParam) {
119             this.validityChanged();
120             return;
121         }
122
123         this.filteredInputProps = _.map(
124             _.filter(
125                 this.getPrimitiveSubtypes(),
126                 prop => !this.param.type || prop.type === this.param.type
127             ),
128             prop => new DropdownValue(prop.uniqueId, prop.name)
129         );
130         this.filteredInputProps.unshift(new DropdownValue("", ""));
131
132         this.operationOutputCats = _.filter(
133             _.map(
134                 this.operationOutputs,
135                 op => {
136                     return {
137                         operationName: `${op.displayType()}.${op.name}`,
138                         outputs: _.map(
139                             _.filter(op.outputs.listToscaDataDefinition, output => !this.param.type || output.type === this.param.type),
140                             output => new DropdownValueType(
141                                 `${op.interfaceType}.${op.name}.${output.name}`,
142                                 output.name,
143                                 output.type
144                             )
145                         )
146                     };
147                 }
148             ),
149             category => category.outputs.length > 0
150         );
151
152         this.filteredCapabilitiesProps = _.filter(
153             _.map(
154                 this.capabilitiesProps,
155                 cap => {
156                     return {
157                         capabilityName: cap.name,
158                         properties: _.map(
159                             _.filter(cap.properties, prop => !this.param.type || prop.type === this.param.type),
160                             prop => new DropdownValueType(
161                                 prop.uniqueId,
162                                 prop.name,
163                                 prop.type
164                             )
165                         )
166                     };
167                 }
168             ),
169             capability => capability.properties.length > 0
170         );
171
172         if (this.param.inputId) {
173             const selProp = this.getSelectedProp();
174             if (selProp && selProp.type === this.param.type) {
175                 this.param.inputId = '-1';
176                 setTimeout(() => this.param.inputId = selProp.uniqueId || selProp.value);
177             } else {
178                 this.param.inputId = null;
179             }
180         }
181
182         this.validityChanged();
183     }
184
185     onChangeProperty() {
186         const newProp = this.getSelectedProp();
187
188         if (!this.param.type) {
189             this.param.type = newProp.type;
190             this.onChangeType();
191         }
192
193         if (!this.param.name) {
194             this.param.name = newProp.name || newProp.label;
195         }
196
197         this.validityChanged();
198     }
199
200     getPrimitiveSubtypes(): Array<InputBEModel> {
201         const flattenedProps: Array<any> = [];
202         const dataTypes = this.dataTypeService.getDataTypeByModel(this.workspaceService.metadata.model);
203
204         _.forEach(this.inputProps, prop => {
205             const type: DataTypeModel = _.find(
206                 _.toArray(dataTypes),
207                 (type: DataTypeModel) => type.name === prop.type
208             );
209             flattenedProps.push(prop);
210             if (!type) {
211                 console.error('Could not find prop in dataTypes: ', prop);
212             } else {
213                 if (type.properties) {
214                     _.forEach(type.properties, subType => {
215                         if (this.isTypePrimitive(subType.type)) {
216                             flattenedProps.push({
217                                 type: subType.type,
218                                 name: `${prop.name}.${subType.name}`,
219                                 uniqueId: `${prop.uniqueId}.${subType.name}`
220                             });
221                         }
222                     });
223                 }
224             }
225         });
226
227         return flattenedProps;
228     }
229
230     getSelectedProp() {
231         return _.find(
232             this.getPrimitiveSubtypes(),
233             prop => this.param.inputId === prop.uniqueId
234         ) || _.find(
235             _.reduce(
236                 this.operationOutputCats,
237                 (acc, cat) => [...acc, ...cat.outputs],
238                 []),
239             (out: DropdownValueType) => this.param.inputId === out.value
240         ) || _.find(
241             _.reduce(
242                 this.filteredCapabilitiesProps,
243                 (acc, cap) => [...acc, ...cap.properties],
244                 []),
245             (prop: DropdownValueType) => this.param.inputId === prop.value
246         );
247     }
248
249     isTypePrimitive(type: string): boolean {
250         return (
251             type === 'string' ||
252             type === 'integer' ||
253             type === 'float' ||
254             type === 'boolean'
255         );
256     }
257 }