* SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
-
-import {Component} from '@angular/core';
+import {Component, EventEmitter, Output, ViewChild} from '@angular/core';
+import { FormControl } from '@angular/forms';
import {UIInterfaceModel} from "../interface-operations.component";
-import {
- InputOperationParameter,
- InterfaceOperationModel,
- IOperationParamsList
-} from "../../../../../models/interfaceOperation";
+import {InputOperationParameter, InterfaceOperationModel, IOperationParamsList} from "../../../../../models/interfaceOperation";
import {TranslateService} from "../../../../shared/translator/translate.service";
+import {DropdownValue} from "../../../../components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {ArtifactModel} from "../../../../../models/artifacts";
+import {PropertyBEModel} from "../../../../../models/properties-inputs/property-be-model";
+import {PropertyParamRowComponent} from "./property-param-row/property-param-row.component";
+import {PropertyFEModel} from "../../../../../models/properties-inputs/property-fe-model";
+import {IDropDownOption} from 'onap-ui-angular';
+import {ComponentServiceNg2} from "../../../../services/component-services/component.service";
+import {DropDownComponent} from "onap-ui-angular/dist/form-elements/dropdown/dropdown.component";
+import {DataTypeService} from "../../../../services/data-type.service";
+import {Observable} from "rxjs/Observable";
+import {DataTypeModel} from "../../../../../models/data-types";
+import {InstanceFeDetails} from "../../../../../models/instance-fe-details";
+import {TopologyTemplateService} from "app/ng2/services/component-services/topology-template.service";
+import {CustomToscaFunction} from "../../../../../models/default-custom-functions";
@Component({
selector: 'operation-handler',
styleUrls: ['./interface-operation-handler.component.less'],
providers: [TranslateService]
})
-
export class InterfaceOperationHandlerComponent {
+ @Output('propertyChanged') emitter: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>();
+ @ViewChild('interfaceOperationDropDown') interfaceOperationDropDown: DropDownComponent;
+
input: {
+ componentInstanceMap: Map<string, InstanceFeDetails>;
+ toscaArtifactTypes: Array<DropdownValue>;
selectedInterface: UIInterfaceModel;
selectedInterfaceOperation: InterfaceOperationModel;
validityChangedCallback: Function;
+ isViewOnly: boolean;
+ isEdit: boolean;
+ validImplementationProps:boolean;
+ modelName: string;
};
+ dataTypeMap$: Observable<Map<string, DataTypeModel>>;
+ dataTypeMap: Map<string, DataTypeModel>;
interfaceType: string;
+ artifactVersion: string;
+ artifactName: string;
interfaceOperationName: string;
operationToUpdate: InterfaceOperationModel;
inputs: Array<InputOperationParameter> = [];
+ properties: Array<PropertyParamRowComponent> = [];
isLoading: boolean = false;
- readonly: boolean;
+ isViewOnly: boolean;
+ isEdit: boolean;
+ validImplementationProps:boolean;
+ interfaceTypes: Array<DropdownValue> = [];
+ interfaceTypeOptions: Array<DropDownOption> = [];
+ selectedInterfaceType: DropDownOption = undefined;
+ interfaceOperationMap: Map<string, Array<string>> = new Map<string, Array<string>>();
+ interfaceOperationOptions: Array<DropDownOption> = [];
+ selectedInterfaceOperation: DropDownOption = undefined;
+ modelName: string;
+ toscaArtifactTypeSelected: string;
+ toscaArtifactTypeProperties: Array<PropertyBEModel> = [];
+ artifactTypeProperties: Array<InputOperationParameter> = [];
+ toscaArtifactTypes: Array<DropdownValue> = [];
+ componentInstanceMap: Map<string, InstanceFeDetails>;
+ customToscaFunctions: Array<CustomToscaFunction>;
+ enableAddArtifactImplementation: boolean;
+ propertyValueValid: boolean = true;
+ inputTypeOptions: any[];
+ timeoutValue = new FormControl('');
+ timeoutType = new FormControl('');
+
+ constructor(private dataTypeService: DataTypeService,
+ private componentServiceNg2: ComponentServiceNg2,
+ private topologyTemplateService: TopologyTemplateService) {
+ }
ngOnInit() {
- this.interfaceType = this.input.selectedInterface.displayType();
+ this.isViewOnly = this.input.isViewOnly;
+ this.isEdit = this.input.isEdit;
+ this.validImplementationProps = this.input.validImplementationProps;
+ this.componentInstanceMap = this.input.componentInstanceMap ? this.input.componentInstanceMap : null;
+ this.interfaceType = this.input.selectedInterface.type;
this.operationToUpdate = new InterfaceOperationModel(this.input.selectedInterfaceOperation);
this.operationToUpdate.interfaceId = this.input.selectedInterface.uniqueId;
this.operationToUpdate.interfaceType = this.input.selectedInterface.type;
+ this.modelName = this.input.modelName;
+ this.timeoutType.setValue('sec');
+ if (this.operationToUpdate.implementation && this.operationToUpdate.implementation.timeout != null) {
+ this.timeoutValue.setValue(this.operationToUpdate.implementation.timeout);
+ let timeout = this.timeoutValue.value / 3600;
+ if (Number.isInteger(timeout)) {
+ if (timeout > 23 && Number.isInteger(timeout / 24)) {
+ this.timeoutValue.setValue(timeout / 24);
+ this.timeoutType.setValue("day");
+ } else {
+ this.timeoutValue.setValue(timeout);
+ this.timeoutType.setValue("hour");
+ }
+ } else if (Number.isInteger(timeout / 24)) {
+ this.timeoutValue.setValue(timeout / 24);
+ this.timeoutType.setValue("day");
+ }
+ }
+ this.initCustomToscaFunctions();
+ this.initInputs();
+ this.removeImplementationQuote();
+ this.loadInterfaceOperationImplementation();
+
+ this.dataTypeMap$ = new Observable<Map<string, DataTypeModel>>(subscriber => {
+ this.dataTypeService.findAllDataTypesByModel(this.modelName)
+ .then((dataTypesMap: Map<string, DataTypeModel>) => {
+ subscriber.next(dataTypesMap);
+ });
+ });
+ this.dataTypeMap$.subscribe(value => {
+ this.dataTypeMap = value;
+ });
+ }
+
+ private initInputs() {
if (!this.operationToUpdate.inputs) {
this.operationToUpdate.inputs = new class implements IOperationParamsList {
listToscaDataDefinition: Array<InputOperationParameter> = [];
}
}
- this.inputs = this.operationToUpdate.inputs.listToscaDataDefinition;
+
+ this.inputs = Array.from(this.operationToUpdate.inputs.listToscaDataDefinition);
this.removeImplementationQuote();
- this.validityChanged();
+ this.loadInterfaceOperationImplementation();
+ this.loadInterfaceType();
+ }
+
+ private initCustomToscaFunctions() {
+ this.customToscaFunctions = [];
+ this.topologyTemplateService.getDefaultCustomFunction().toPromise().then((data) => {
+ if (data) {
+ for (let customFunction of data) {
+ this.customToscaFunctions.push(new CustomToscaFunction(customFunction));
+ }
+ }
+ });
+ }
+
+ private loadInterfaceType() {
+ this.componentServiceNg2.getInterfaceTypesByModel(this.modelName)
+ .subscribe(response => {
+ if (response) {
+ this.interfaceOperationMap = new Map<string, Array<string>>();
+ for (const interfaceType of Object.keys(response).sort()) {
+ const operationList = response[interfaceType];
+ operationList.sort();
+ this.interfaceOperationMap.set(interfaceType, operationList);
+ const operationDropDownOption: DropDownOption = new DropDownOption(interfaceType);
+ this.interfaceTypeOptions.push(operationDropDownOption);
+ if (this.interfaceType == interfaceType) {
+ this.selectedInterfaceType = operationDropDownOption;
+ }
+ }
+ this.loadInterfaceTypeOperations();
+ }
+ });
+ }
+
+ loadInterfaceTypeOperations() {
+ this.interfaceOperationOptions = new Array<DropDownOption>();
+ const interfaceOperationList = this.interfaceOperationMap.get(this.interfaceType);
+
+ if (interfaceOperationList) {
+ interfaceOperationList.forEach(operationName => {
+ const operationOption = new DropDownOption(operationName, operationName);
+ this.interfaceOperationOptions.push(operationOption);
+ if (this.operationToUpdate.name == operationName) {
+ this.selectedInterfaceOperation = operationOption
+ }
+ });
+ }
+
+ this.interfaceOperationDropDown.allOptions = this.interfaceOperationOptions;
+ }
+
+ private loadInterfaceOperationImplementation() {
+ this.toscaArtifactTypes = this.input.toscaArtifactTypes;
+ if (this.operationToUpdate.implementation) {
+ this.artifactVersion = this.operationToUpdate.implementation.artifactVersion;
+ this.artifactName = this.operationToUpdate.implementation.artifactName;
+ this.toscaArtifactTypeProperties = this.operationToUpdate.implementation.properties;
+ }
+ this.artifactTypeProperties = this.convertArtifactsPropertiesToInput();
+ this.getArtifactTypesSelected();
+ }
+
+ onDescriptionChange = (value: any): void => {
+ this.operationToUpdate.description = value;
+ }
+
+ onURIChange(value: string | undefined) {
+ if(!this.operationToUpdate.implementation){
+ let artifact = new ArtifactModel();
+ this.operationToUpdate.implementation = artifact;
+ }
+ this.operationToUpdate.implementation.artifactName = value ? value : '';
+ }
+
+ onPropertyValueChange = (propertyValue) => {
+ this.emitter.emit(propertyValue);
+ }
+
+ onMarkToAddArtifactToImplementation(event: boolean) {
+ if (!event) {
+ this.toscaArtifactTypeSelected = undefined;
+ this.artifactVersion = undefined;
+ if (this.operationToUpdate.implementation.artifactType) {
+ this.operationToUpdate.implementation.artifactVersion = '';
+ this.operationToUpdate.implementation.artifactType = '';
+ }
+ this.toscaArtifactTypeProperties = undefined;
+ this.artifactTypeProperties = undefined;
+ } else {
+ this.getArtifactTypesSelected();
+ }
+ this.enableAddArtifactImplementation = event;
+ }
+
+ onSelectToscaArtifactType(type: IDropDownOption) {
+ if (type) {
+ let toscaArtifactType = type.value;
+ let artifact = new ArtifactModel();
+ artifact.artifactName = this.operationToUpdate.implementation.artifactName;
+ artifact.artifactVersion = this.operationToUpdate.implementation.artifactVersion;
+ artifact.artifactType = toscaArtifactType.type;
+ artifact.properties = toscaArtifactType.properties;
+ this.toscaArtifactTypeProperties = artifact.properties;
+ this.artifactTypeProperties = this.convertArtifactsPropertiesToInput();
+ this.toscaArtifactTypeSelected = artifact.artifactType;
+ this.operationToUpdate.implementation = artifact;
+ this.getArtifactTypesSelected();
+ }
+ }
+
+ onArtifactVersionChange(value: string | undefined) {
+ this.operationToUpdate.implementation.artifactVersion = value ? value : '';
+ }
+
+ onAddInput(inputOperationParameter: InputOperationParameter) {
+ this.addInput(inputOperationParameter);
}
- onAddInput(inputOperationParameter?: InputOperationParameter): void {
- let newInput = new InputOperationParameter(inputOperationParameter)
- newInput.type = "string";
- newInput.inputId = this.generateUniqueId();
- this.inputs.push(newInput);
- this.validityChanged();
+ propertyValueValidation = (propertyValue): void => {
+ this.onPropertyValueChange(propertyValue);
+ this.propertyValueValid = propertyValue.isValid;
}
onRemoveInput = (inputParam: InputOperationParameter): void => {
let index = this.inputs.indexOf(inputParam);
this.inputs.splice(index, 1);
- this.validityChanged();
}
- private generateUniqueId = (): string => {
- let result = '';
- const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
- const charactersLength = characters.length;
- for (let i = 0; i < 36; i++ ) {
- result += characters.charAt(Math.floor(Math.random() * charactersLength));
+ timeoutConversion = (): void => {
+ let timeout = this.timeoutValue.value;
+ if (timeout != null) {
+ if (this.timeoutType.value == null || this.timeoutType.value == 'sec') {
+ this.operationToUpdate.implementation.timeout = timeout;
+ return;
+ }
+ if (this.timeoutType.value == 'hour') {
+ this.operationToUpdate.implementation.timeout = timeout * 3600;
+ } else if (this.timeoutType.value == 'day') {
+ this.operationToUpdate.implementation.timeout = (timeout * 24) * 3600;
+ }
}
- return result;
}
- validityChanged = () => {
- let validState = this.checkFormValidForSubmit();
- this.input.validityChangedCallback(validState);
- if (validState) {
- this.readonly = false;
+ private removeImplementationQuote(): void {
+ if (this.operationToUpdate.implementation) {
+ if (!this.operationToUpdate.implementation
+ || !this.operationToUpdate.implementation.artifactName) {
+ return;
+ }
+
+ let implementation = this.operationToUpdate.implementation.artifactName.trim();
+
+ if (implementation.startsWith("'") && implementation.endsWith("'")) {
+ this.operationToUpdate.implementation.artifactName = implementation.slice(1, -1);
+ }
}
}
- onDescriptionChange= (value: any): void => {
- this.operationToUpdate.description = value;
+ private getArtifactTypesSelected() {
+ if (this.operationToUpdate.implementation && this.operationToUpdate.implementation.artifactType) {
+ this.artifactName =
+ this.artifactName ? this.artifactName : this.operationToUpdate.implementation.artifactName;
+ this.toscaArtifactTypeSelected = this.operationToUpdate.implementation.artifactType;
+ this.artifactVersion =
+ this.artifactVersion ? this.artifactVersion : this.operationToUpdate.implementation.artifactVersion;
+ this.toscaArtifactTypeProperties = this.operationToUpdate.implementation.properties;
+ this.artifactTypeProperties = this.convertArtifactsPropertiesToInput();
+ this.enableAddArtifactImplementation = true;
+ }
}
- private checkFormValidForSubmit = (): boolean => {
- return this.operationToUpdate.name && this.isParamsValid();
+ toDropDownOption(val: string) {
+ return { value : val, label: val };
}
- private isParamsValid = (): boolean => {
- const isInputValid = (input) => input.name && input.inputId;
- const isValid = this.inputs.every(isInputValid);
- if (!isValid) {
- this.readonly = true;
+ /**
+ * Handles the input value change event.
+ * @param changedInput the changed input
+ */
+ onInputValueChange(changedInput: InputOperationParameter) {
+ if (changedInput.value instanceof Object) {
+ changedInput.value = JSON.stringify(changedInput.value);
+ }
+ const inputOperationParameter = this.inputs.find(value => value.name == changedInput.name);
+ inputOperationParameter.toscaFunction = null;
+ inputOperationParameter.value = changedInput.value;
+ inputOperationParameter.subPropertyToscaFunctions = changedInput.subPropertyToscaFunctions;
+ if (changedInput.isToscaFunction()) {
+ inputOperationParameter.toscaFunction = changedInput.toscaFunction;
+ inputOperationParameter.value = changedInput.toscaFunction.buildValueString();
}
- return isValid;
}
- private removeImplementationQuote(): void {
- if (!this.operationToUpdate.implementation
- || !this.operationToUpdate.implementation.artifactName) {
+ onArtifactPropertyValueChange(changedProperty: InputOperationParameter) {
+ const property = this.toscaArtifactTypeProperties.find(artifactProperty => artifactProperty.name == changedProperty.name);
+ if (changedProperty.value instanceof Object) {
+ changedProperty.value = JSON.stringify(changedProperty.value);
+ }
+ property.toscaFunction = null;
+ property.value = changedProperty.value;
+ if (changedProperty.isToscaFunction()) {
+ property.toscaFunction = changedProperty.toscaFunction;
+ property.value = changedProperty.toscaFunction.buildValueString();
+ }
+ }
+
+ implementationPropsValidityChange(validImplementationProps: boolean) {
+ this.validImplementationProps = validImplementationProps;
+ }
+
+ /**
+ * Handles the add input event.
+ * @param input the input to add
+ * @private
+ */
+ private addInput(input: InputOperationParameter) {
+ this.operationToUpdate.inputs.listToscaDataDefinition.push(input);
+ this.inputs = Array.from(this.operationToUpdate.inputs.listToscaDataDefinition);
+ }
+
+ /**
+ * Return a list with current input names.
+ */
+ collectInputNames() {
+ return this.inputs.map((input) => input.name);
+ }
+
+ /**
+ * Handles the delete input event.
+ * @param inputName the name of the input to be deleted
+ */
+ onInputDelete(inputName: string) {
+ const currentInputs = this.operationToUpdate.inputs.listToscaDataDefinition;
+ const input1 = currentInputs.find(value => value.name === inputName);
+ const indexOfInput = currentInputs.indexOf(input1);
+ if (indexOfInput === -1) {
+ console.error(`Could not delete input '${inputName}'. Input not found.`);
return;
}
+ currentInputs.splice(currentInputs.indexOf(input1), 1);
+ this.inputs = Array.from(currentInputs);
+ }
- let implementation = this.operationToUpdate.implementation.artifactName.trim();
+ private convertArtifactsPropertiesToInput(): Array<InputOperationParameter> {
+ if (!this.toscaArtifactTypeProperties) {
+ return [];
+ }
+ const inputList: Array<InputOperationParameter> = [];
+ this.toscaArtifactTypeProperties.forEach(property => {
+ const input = new InputOperationParameter();
+ input.name = property.name;
+ input.type = property.type;
+ input.schema = property.schema;
+ input.toscaDefaultValue = property.defaultValue;
+ input.value = property.value;
+ input.toscaFunction = property.toscaFunction;
+ inputList.push(input);
+ });
+ return inputList;
+ }
- if (implementation.startsWith("'") && implementation.endsWith("'")) {
- this.operationToUpdate.implementation.artifactName = implementation.slice(1, -1);
+ onSelectInterface(dropDownOption: DropDownOption) {
+ if (dropDownOption) {
+ this.setInterfaceType(dropDownOption);
+ } else {
+ this.setInterfaceType(undefined);
}
+ this.setInterfaceOperation(undefined);
+ this.interfaceOperationDropDown.selectOption({} as IDropDownOption);
+ this.loadInterfaceTypeOperations();
}
+ onSelectOperation(dropDownOption: DropDownOption) {
+ if (this.selectedInterfaceType && dropDownOption) {
+ this.setInterfaceOperation(dropDownOption);
+ }
+ }
+
+ private setInterfaceType(dropDownOption: DropDownOption) {
+ this.selectedInterfaceType = dropDownOption ? dropDownOption : undefined;
+ this.interfaceType = dropDownOption ? dropDownOption.value : undefined;
+ this.operationToUpdate.interfaceType = dropDownOption ? dropDownOption.value : undefined;
+ this.operationToUpdate.interfaceId = dropDownOption ? dropDownOption.value : undefined;
+ }
+
+ private setInterfaceOperation(dropDownOption: DropDownOption) {
+ this.operationToUpdate.name = dropDownOption ? dropDownOption.value : undefined;
+ this.operationToUpdate.operationType = dropDownOption ? dropDownOption.value : undefined;
+ this.selectedInterfaceOperation = dropDownOption ? dropDownOption : undefined;
+ }
}
+
+class DropDownOption implements IDropDownOption {
+ value: string;
+ label: string;
+
+ constructor(value: string, label?: string) {
+ this.value = value;
+ this.label = label || value;
+ }
+}
\ No newline at end of file