2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2021 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
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
21 import {Component, EventEmitter, Output, ViewChild} from '@angular/core';
22 import {UIInterfaceModel} from "../interface-operations.component";
23 import {InputOperationParameter, InterfaceOperationModel, IOperationParamsList} from "../../../../../models/interfaceOperation";
24 import {TranslateService} from "../../../../shared/translator/translate.service";
25 import {DropdownValue} from "../../../../components/ui/form-components/dropdown/ui-element-dropdown.component";
26 import {ArtifactModel} from "../../../../../models/artifacts";
27 import {PropertyBEModel} from "../../../../../models/properties-inputs/property-be-model";
28 import {PropertyParamRowComponent} from "./property-param-row/property-param-row.component";
29 import {PropertyFEModel} from "../../../../../models/properties-inputs/property-fe-model";
30 import {IDropDownOption} from 'onap-ui-angular';
31 import {ComponentServiceNg2} from "../../../../services/component-services/component.service";
32 import {DropDownComponent} from "onap-ui-angular/dist/form-elements/dropdown/dropdown.component";
33 import {DataTypeService} from "../../../../services/data-type.service";
34 import {Observable} from "rxjs/Observable";
35 import {DataTypeModel} from "../../../../../models/data-types";
36 import {InstanceFeDetails} from "../../../../../models/instance-fe-details";
37 import {TopologyTemplateService} from "app/ng2/services/component-services/topology-template.service";
38 import {CustomToscaFunction} from "../../../../../models/default-custom-functions";
39 import {ToscaFunctionType} from "../../../../../models/tosca-function-type.enum";
42 selector: 'operation-handler',
43 templateUrl: './interface-operation-handler.component.html',
44 styleUrls: ['./interface-operation-handler.component.less'],
45 providers: [TranslateService]
47 export class InterfaceOperationHandlerComponent {
49 @Output('propertyChanged') emitter: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>();
50 @ViewChild('interfaceOperationDropDown') interfaceOperationDropDown: DropDownComponent;
53 componentInstanceMap: Map<string, InstanceFeDetails>;
54 toscaArtifactTypes: Array<DropdownValue>;
55 selectedInterface: UIInterfaceModel;
56 selectedInterfaceOperation: InterfaceOperationModel;
57 validityChangedCallback: Function;
60 validImplementationProps:boolean;
64 dataTypeMap$: Observable<Map<string, DataTypeModel>>;
65 dataTypeMap: Map<string, DataTypeModel>;
66 interfaceType: string;
67 artifactVersion: string;
69 interfaceOperationName: string;
70 operationToUpdate: InterfaceOperationModel;
71 inputs: Array<InputOperationParameter> = [];
72 properties: Array<PropertyParamRowComponent> = [];
73 isLoading: boolean = false;
76 validImplementationProps:boolean;
77 interfaceTypes: Array<DropdownValue> = [];
78 interfaceTypeOptions: Array<DropDownOption> = [];
79 selectedInterfaceType: DropDownOption = undefined;
80 interfaceOperationMap: Map<string, Array<string>> = new Map<string, Array<string>>();
81 interfaceOperationOptions: Array<DropDownOption> = [];
82 selectedInterfaceOperation: DropDownOption = undefined;
84 toscaArtifactTypeSelected: string;
85 toscaArtifactTypeProperties: Array<PropertyBEModel> = [];
86 artifactTypeProperties: Array<InputOperationParameter> = [];
87 toscaArtifactTypes: Array<DropdownValue> = [];
88 componentInstanceMap: Map<string, InstanceFeDetails>;
89 customToscaFunctions: Array<CustomToscaFunction>;
90 enableAddArtifactImplementation: boolean;
91 propertyValueValid: boolean = true;
92 inputTypeOptions: any[];
94 constructor(private dataTypeService: DataTypeService,
95 private componentServiceNg2: ComponentServiceNg2,
96 private topologyTemplateService: TopologyTemplateService) {
100 this.isViewOnly = this.input.isViewOnly;
101 this.isEdit = this.input.isEdit;
102 this.validImplementationProps = this.input.validImplementationProps;
103 this.componentInstanceMap = this.input.componentInstanceMap ? this.input.componentInstanceMap : null;
104 this.interfaceType = this.input.selectedInterface.type;
105 this.operationToUpdate = new InterfaceOperationModel(this.input.selectedInterfaceOperation);
106 this.operationToUpdate.interfaceId = this.input.selectedInterface.uniqueId;
107 this.operationToUpdate.interfaceType = this.input.selectedInterface.type;
108 this.modelName = this.input.modelName;
109 this.initCustomToscaFunctions();
111 this.removeImplementationQuote();
112 this.loadInterfaceOperationImplementation();
114 this.dataTypeMap$ = new Observable<Map<string, DataTypeModel>>(subscriber => {
115 this.dataTypeService.findAllDataTypesByModel(this.modelName)
116 .then((dataTypesMap: Map<string, DataTypeModel>) => {
117 subscriber.next(dataTypesMap);
120 this.dataTypeMap$.subscribe(value => {
121 this.dataTypeMap = value;
125 private initInputs() {
126 if (!this.operationToUpdate.inputs) {
127 this.operationToUpdate.inputs = new class implements IOperationParamsList {
128 listToscaDataDefinition: Array<InputOperationParameter> = [];
132 this.inputs = Array.from(this.operationToUpdate.inputs.listToscaDataDefinition);
133 this.removeImplementationQuote();
134 this.loadInterfaceOperationImplementation();
135 this.loadInterfaceType();
138 private initCustomToscaFunctions() {
139 this.customToscaFunctions = [];
140 this.topologyTemplateService.getDefaultCustomFunction().toPromise().then((data) => {
142 for (let customFunction of data) {
143 this.customToscaFunctions.push(new CustomToscaFunction(customFunction));
149 private loadInterfaceType() {
150 this.componentServiceNg2.getInterfaceTypesByModel(this.modelName)
151 .subscribe(response => {
153 this.interfaceOperationMap = new Map<string, Array<string>>();
154 for (const interfaceType of Object.keys(response).sort()) {
155 const operationList = response[interfaceType];
156 operationList.sort();
157 this.interfaceOperationMap.set(interfaceType, operationList);
158 const operationDropDownOption: DropDownOption = new DropDownOption(interfaceType);
159 this.interfaceTypeOptions.push(operationDropDownOption);
160 if (this.interfaceType == interfaceType) {
161 this.selectedInterfaceType = operationDropDownOption;
164 this.loadInterfaceTypeOperations();
169 loadInterfaceTypeOperations() {
170 this.interfaceOperationOptions = new Array<DropDownOption>();
171 const interfaceOperationList = this.interfaceOperationMap.get(this.interfaceType);
173 if (interfaceOperationList) {
174 interfaceOperationList.forEach(operationName => {
175 const operationOption = new DropDownOption(operationName, operationName);
176 this.interfaceOperationOptions.push(operationOption);
177 if (this.operationToUpdate.name == operationName) {
178 this.selectedInterfaceOperation = operationOption
183 this.interfaceOperationDropDown.allOptions = this.interfaceOperationOptions;
186 private loadInterfaceOperationImplementation() {
187 this.toscaArtifactTypes = this.input.toscaArtifactTypes;
188 if (this.operationToUpdate.implementation) {
189 this.artifactVersion = this.operationToUpdate.implementation.artifactVersion;
190 this.artifactName = this.operationToUpdate.implementation.artifactName;
191 this.toscaArtifactTypeProperties = this.operationToUpdate.implementation.properties;
193 this.artifactTypeProperties = this.convertArtifactsPropertiesToInput();
194 this.getArtifactTypesSelected();
197 onDescriptionChange = (value: any): void => {
198 this.operationToUpdate.description = value;
201 onURIChange(value: string | undefined) {
202 if(!this.operationToUpdate.implementation){
203 let artifact = new ArtifactModel();
204 this.operationToUpdate.implementation = artifact;
206 this.operationToUpdate.implementation.artifactName = value ? value : '';
209 onPropertyValueChange = (propertyValue) => {
210 this.emitter.emit(propertyValue);
213 onMarkToAddArtifactToImplementation(event: boolean) {
215 this.toscaArtifactTypeSelected = undefined;
216 this.artifactVersion = undefined;
217 if (this.operationToUpdate.implementation.artifactType) {
218 this.operationToUpdate.implementation.artifactVersion = '';
219 this.operationToUpdate.implementation.artifactType = '';
221 this.toscaArtifactTypeProperties = undefined;
222 this.artifactTypeProperties = undefined;
224 this.getArtifactTypesSelected();
226 this.enableAddArtifactImplementation = event;
229 onSelectToscaArtifactType(type: IDropDownOption) {
231 let toscaArtifactType = type.value;
232 let artifact = new ArtifactModel();
233 artifact.artifactName = this.operationToUpdate.implementation.artifactName;
234 artifact.artifactVersion = this.operationToUpdate.implementation.artifactVersion;
235 artifact.artifactType = toscaArtifactType.type;
236 artifact.properties = toscaArtifactType.properties;
237 this.toscaArtifactTypeProperties = artifact.properties;
238 this.artifactTypeProperties = this.convertArtifactsPropertiesToInput();
239 this.toscaArtifactTypeSelected = artifact.artifactType;
240 this.operationToUpdate.implementation = artifact;
241 this.getArtifactTypesSelected();
245 onArtifactVersionChange(value: string | undefined) {
246 this.operationToUpdate.implementation.artifactVersion = value ? value : '';
249 onAddInput(inputOperationParameter: InputOperationParameter) {
250 this.addInput(inputOperationParameter);
253 propertyValueValidation = (propertyValue): void => {
254 this.onPropertyValueChange(propertyValue);
255 this.propertyValueValid = propertyValue.isValid;
258 onRemoveInput = (inputParam: InputOperationParameter): void => {
259 let index = this.inputs.indexOf(inputParam);
260 this.inputs.splice(index, 1);
263 private removeImplementationQuote(): void {
264 if (this.operationToUpdate.implementation) {
265 if (!this.operationToUpdate.implementation
266 || !this.operationToUpdate.implementation.artifactName) {
270 let implementation = this.operationToUpdate.implementation.artifactName.trim();
272 if (implementation.startsWith("'") && implementation.endsWith("'")) {
273 this.operationToUpdate.implementation.artifactName = implementation.slice(1, -1);
278 private getArtifactTypesSelected() {
279 if (this.operationToUpdate.implementation && this.operationToUpdate.implementation.artifactType) {
281 this.artifactName ? this.artifactName : this.operationToUpdate.implementation.artifactName;
282 this.toscaArtifactTypeSelected = this.operationToUpdate.implementation.artifactType;
283 this.artifactVersion =
284 this.artifactVersion ? this.artifactVersion : this.operationToUpdate.implementation.artifactVersion;
285 this.toscaArtifactTypeProperties = this.operationToUpdate.implementation.properties;
286 this.artifactTypeProperties = this.convertArtifactsPropertiesToInput();
287 this.enableAddArtifactImplementation = true;
291 toDropDownOption(val: string) {
292 return { value : val, label: val };
296 * Handles the input value change event.
297 * @param changedInput the changed input
299 onInputValueChange(changedInput: InputOperationParameter) {
300 if (changedInput.value instanceof Object) {
301 changedInput.value = JSON.stringify(changedInput.value);
303 const inputOperationParameter = this.inputs.find(value => value.name == changedInput.name);
304 inputOperationParameter.toscaFunction = null;
305 inputOperationParameter.value = changedInput.value;
306 if (inputOperationParameter.subPropertyToscaFunctions) {
307 inputOperationParameter.subPropertyToscaFunctions = undefined;
309 if (changedInput.isToscaFunction()) {
310 inputOperationParameter.toscaFunction = changedInput.toscaFunction;
311 inputOperationParameter.value = changedInput.toscaFunction.buildValueString();
315 onArtifactPropertyValueChange(changedProperty: InputOperationParameter) {
316 const property = this.toscaArtifactTypeProperties.find(artifactProperty => artifactProperty.name == changedProperty.name);
317 if (changedProperty.value instanceof Object) {
318 changedProperty.value = JSON.stringify(changedProperty.value);
320 property.toscaFunction = null;
321 property.value = changedProperty.value;
322 if (changedProperty.isToscaFunction()) {
323 property.toscaFunction = changedProperty.toscaFunction;
324 property.value = changedProperty.toscaFunction.buildValueString();
328 implementationPropsValidityChange(validImplementationProps: boolean) {
329 this.validImplementationProps = validImplementationProps;
333 * Handles the add input event.
334 * @param input the input to add
337 private addInput(input: InputOperationParameter) {
338 this.operationToUpdate.inputs.listToscaDataDefinition.push(input);
339 this.inputs = Array.from(this.operationToUpdate.inputs.listToscaDataDefinition);
343 * Return a list with current input names.
345 collectInputNames() {
346 return this.inputs.map((input) => input.name);
350 * Handles the delete input event.
351 * @param inputName the name of the input to be deleted
353 onInputDelete(inputName: string) {
354 const currentInputs = this.operationToUpdate.inputs.listToscaDataDefinition;
355 const input1 = currentInputs.find(value => value.name === inputName);
356 const indexOfInput = currentInputs.indexOf(input1);
357 if (indexOfInput === -1) {
358 console.error(`Could not delete input '${inputName}'. Input not found.`);
361 currentInputs.splice(currentInputs.indexOf(input1), 1);
362 this.inputs = Array.from(currentInputs);
365 private convertArtifactsPropertiesToInput(): Array<InputOperationParameter> {
366 if (!this.toscaArtifactTypeProperties) {
369 const inputList: Array<InputOperationParameter> = [];
370 this.toscaArtifactTypeProperties.forEach(property => {
371 const input = new InputOperationParameter();
372 input.name = property.name;
373 input.type = property.type;
374 input.schema = property.schema;
375 input.toscaDefaultValue = property.defaultValue;
376 input.value = property.value;
377 input.toscaFunction = property.toscaFunction;
378 inputList.push(input);
383 onSelectInterface(dropDownOption: DropDownOption) {
384 if (dropDownOption) {
385 this.setInterfaceType(dropDownOption);
387 this.setInterfaceType(undefined);
389 this.setInterfaceOperation(undefined);
390 this.interfaceOperationDropDown.selectOption({} as IDropDownOption);
391 this.loadInterfaceTypeOperations();
394 onSelectOperation(dropDownOption: DropDownOption) {
395 if (this.selectedInterfaceType && dropDownOption) {
396 this.setInterfaceOperation(dropDownOption);
400 private setInterfaceType(dropDownOption: DropDownOption) {
401 this.selectedInterfaceType = dropDownOption ? dropDownOption : undefined;
402 this.interfaceType = dropDownOption ? dropDownOption.value : undefined;
403 this.operationToUpdate.interfaceType = dropDownOption ? dropDownOption.value : undefined;
404 this.operationToUpdate.interfaceId = dropDownOption ? dropDownOption.value : undefined;
407 private setInterfaceOperation(dropDownOption: DropDownOption) {
408 this.operationToUpdate.name = dropDownOption ? dropDownOption.value : undefined;
409 this.operationToUpdate.operationType = dropDownOption ? dropDownOption.value : undefined;
410 this.selectedInterfaceOperation = dropDownOption ? dropDownOption : undefined;
414 class DropDownOption implements IDropDownOption {
418 constructor(value: string, label?: string) {
420 this.label = label || value;