aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/ng2/pages/composition
diff options
context:
space:
mode:
authoraribeiro <anderson.ribeiro@est.tech>2021-10-01 11:30:49 +0100
committerAndr� Schmid <andre.schmid@est.tech>2021-11-05 17:14:06 +0000
commit1de1692115d1df5b4e07c1feb21d098899a6604b (patch)
tree1e26079e5cc5dc708eb666611f98dd0fc0af571d /catalog-ui/src/app/ng2/pages/composition
parent2b55a906b7115ff2b156b35a4ff66811157111ee (diff)
Add UI support for adding tosca artifact types
UI support for adding artifacts to an interface operation implementation Issue-ID: SDC-3768 Signed-off-by: aribeiro <anderson.ribeiro@est.tech> Change-Id: I71b3e49a160521e35a45515ad7adef836f901e78
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/composition')
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.ts62
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html75
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less18
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts146
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.module.ts12
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.html44
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.less72
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.ts35
8 files changed, 428 insertions, 36 deletions
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.ts b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.ts
index 304fbcec3e..2cc91a92a0 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.ts
@@ -19,7 +19,7 @@
* ============LICENSE_END=========================================================
*/
-import {Component, ComponentRef, Input} from '@angular/core';
+import {Component, ComponentRef, Inject, Input} from '@angular/core';
import {TopologyTemplateService} from '../../../services/component-services/topology-template.service';
import {TranslateService} from "../../../shared/translator/translate.service";
import {ModalService } from 'app/ng2/services/modal.service';
@@ -45,15 +45,17 @@ import {
InterfaceModel,
InputBEModel,
ModalModel,
- ComponentInstance
+ ComponentInstance, ArtifactModel
} from 'app/models';
+import {ArtifactGroupType} from "../../../../utils/constants";
+import {DropdownValue} from "../../../components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {ToscaArtifactService} from "../../../services/tosca-artifact.service";
+import {ToscaArtifactModel} from "../../../../models/toscaArtifact";
export class UIInterfaceOperationModel extends InterfaceOperationModel {
isCollapsed: boolean = true;
isEllipsis: boolean;
MAX_LENGTH = 75;
- _description: string;
-
constructor(operation: InterfaceOperationModel) {
super(operation);
@@ -119,7 +121,6 @@ export class UIInterfaceModel extends ComponentInstanceInterfaceModel {
})
export class InterfaceOperationsComponent {
interfaces: UIInterfaceModel[];
- selectedOperation: InterfaceOperationModel;
inputs: Array<InputBEModel>;
isLoading: boolean;
interfaceTypes: { [interfaceType: string]: string[] };
@@ -130,6 +131,9 @@ export class InterfaceOperationsComponent {
modalTranslation: ModalTranslation;
componentInstancesInterfaces: Map<string, InterfaceModel[]>;
+ deploymentArtifactsFilePath: Array<DropdownValue> = [];
+ toscaArtifactTypes: Array<DropdownValue> = [];
+
@Input() component: ComponentInstance;
@Input() readonly: boolean;
@Input() enableMenuItems: Function;
@@ -141,8 +145,10 @@ export class InterfaceOperationsComponent {
private TranslateService: TranslateService,
private PluginsService: PluginsService,
private topologyTemplateService: TopologyTemplateService,
+ private toscaArtifactService: ToscaArtifactService,
private modalServiceNg2: ModalService,
private workspaceService: WorkspaceService,
+ @Inject("Notification") private Notification: any,
) {
this.modalTranslation = new ModalTranslation(TranslateService);
}
@@ -150,6 +156,8 @@ export class InterfaceOperationsComponent {
ngOnInit(): void {
this.componentMetaData = this.workspaceService.metadata;
this.loadComponentInstances();
+ this.loadDeployedArtifacts();
+ this.loadToscaArtifacts()
}
private loadComponentInstances() {
@@ -167,7 +175,7 @@ export class InterfaceOperationsComponent {
this.sortInterfaces();
}
- private initInterfaces(interfaces: InterfaceModel[]): void {
+ private initInterfaces(interfaces: ComponentInstanceInterfaceModel[]): void {
this.interfaces = _.map(interfaces, (interfaceModel) => new UIInterfaceModel(interfaceModel));
}
@@ -201,7 +209,7 @@ export class InterfaceOperationsComponent {
}
private enableOrDisableSaveButton = (): boolean => {
- return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
+ return this.modalInstance.instance.dynamicContent.instance.readonly;
}
onSelectInterfaceOperation(interfaceModel: UIInterfaceModel, operation: InterfaceOperationModel) {
@@ -215,6 +223,8 @@ export class InterfaceOperationsComponent {
this.modalInstance,
InterfaceOperationHandlerComponent,
{
+ deploymentArtifactsFilePath: this.deploymentArtifactsFilePath,
+ toscaArtifactTypes: this.toscaArtifactTypes,
selectedInterface: interfaceModel,
selectedInterfaceOperation: operation,
validityChangedCallback: this.enableOrDisableSaveButton
@@ -235,13 +245,43 @@ export class InterfaceOperationsComponent {
this.componentMetaData.uniqueId,
this.componentMetaData.componentType,
this.componentInstanceSelected.uniqueId,
- operationUpdated)
- .subscribe((updatedComponentInstance: ComponentInstance) => {
- this.componentInstanceSelected = new ComponentInstance(updatedComponentInstance);
- this.initComponentInstanceInterfaceOperations();
+ operationUpdated).subscribe((updatedComponentInstance: ComponentInstance) => {
+ this.componentInstanceSelected = new ComponentInstance(updatedComponentInstance);
+ this.initComponentInstanceInterfaceOperations();
});
this.modalServiceNg2.closeCurrentModal();
this.isLoading = false;
}
+ loadDeployedArtifacts() {
+ this.topologyTemplateService.getArtifactsByType(this.componentMetaData.componentType, this.componentMetaData.uniqueId, ArtifactGroupType.DEPLOYMENT)
+ .subscribe(response => {
+ let artifactsDeployment = response.deploymentArtifacts;
+ if (artifactsDeployment) {
+ let deploymentArtifactsFound = <ArtifactModel[]>_.values(artifactsDeployment)
+ deploymentArtifactsFound.forEach(value => {
+ this.deploymentArtifactsFilePath.push(new DropdownValue(value, value.artifactType.concat('->').concat(value.artifactName)));
+ });
+ }}, error => {
+ this.Notification.error({
+ message: 'Failed to Load the Deployed Artifacts:' + error,
+ title: 'Failure'
+ });
+ });
+ }
+
+ loadToscaArtifacts() {
+ this.toscaArtifactService.getToscaArtifacts(this.componentMetaData.model).subscribe(response => {
+ if (response) {
+ let toscaArtifactsFound = <ToscaArtifactModel[]>_.values(response);
+ toscaArtifactsFound.forEach(value => this.toscaArtifactTypes.push(new DropdownValue(value, value.type)));
+ }
+ }, error => {
+ this.Notification.error({
+ message: 'Failed to Load Tosca Artifacts:' + error,
+ title: 'Failure'
+ });
+ });
+ }
+
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html
index f71102053a..428c4cd5ed 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html
@@ -41,7 +41,7 @@
</div>
</div>
- <div class="i-sdc-form-item">
+ <div class="form-item">
<sdc-input
label="{{'OPERATION_DESCRIPTION' | translate}}"
[(value)]="operationToUpdate.description"
@@ -50,12 +50,73 @@
</sdc-input>
</div>
- <div class="i-sdc-form-item">
- <sdc-input
- label="{{'IMPLEMENTATION_NAME' | translate}}"
- testId="interface-operation-implementation-name"
- [(value)]="operationToUpdate.implementation.artifactName">
- </sdc-input>
+ <div class="group-with-border content-row">
+ <label class="occurrences-label"> {{ 'INTERFACE_OPERATION_IMPLEMENTATION' | translate}}</label>
+ <div class="form-item">
+ <checkbox [label]="'Add Artifact To Implementation'"
+ [(checked)]="enableAddArtifactImplementation"
+ (checkedChange)="onMarkToAddArtifactToImplementation($event)">
+ </checkbox>
+ </div>
+ <div class="form-item" *ngIf="!enableAddArtifactImplementation">
+ <sdc-input
+ label="{{'INTERFACE_OPERATION_IMPLEMENTATION_NAME' | translate}}"
+ testId="interface-operation-implementation-name"
+ [(value)]="artifactName"
+ (valueChange)="onImplementationNameChange($event)">
+ </sdc-input>
+ </div>
+
+ <div class="side-by-side" *ngIf="enableAddArtifactImplementation">
+ <div class="form-item" *ngIf="toscaArtifactTypes">
+ <sdc-dropdown
+ label="{{ 'TOSCA_ARTIFACT_TYPE' | translate }}"
+ testId="selectToscaArtifactType"
+ [required]="true"
+ [selectedOption]="toscaArtifactTypeSelected"
+ placeHolder="{{toscaArtifactTypeSelected != undefined ? toscaArtifactTypeSelected : 'Select...'}}"
+ (changed)="onSelectToscaArtifactType($event)"
+ [options]="toscaArtifactTypes">
+ </sdc-dropdown>
+ </div>
+ <div class="form-item" *ngIf="toscaArtifactTypeSelected && enableAddArtifactImplementation">
+ <sdc-input
+ label="{{ 'INTERFACE_OPERATION_IMPLEMENTATION_FILE' | translate }}"
+ data-tests-id="artifactFile"
+ [(value)]="artifactName"
+ [required]="true"
+ (valueChange)="onArtifactFileChange($event)">
+ </sdc-input>
+ </div>
+ <div class="form-item">
+ <sdc-input
+ label="{{ 'ARTIFACT_VERSION' | translate }}"
+ data-tests-id="artifactVersion"
+ [(value)]="artifactVersion"
+ (valueChange)="onArtifactVersionChange($event)">
+ </sdc-input>
+ </div>
+ </div>
+ <div class="form-item" *ngIf="toscaArtifactTypeSelected && enableAddArtifactImplementation">
+ <label class="sdc-input__label">{{ 'ENTITY_VIEWER_PROPERTIES_TAB' | translate }}</label>
+ <div class="generic-table">
+ <div class="header-row table-row">
+ <span class="cell header-cell field-input-name">{{ 'IMPLEMENTATION_ARTIFACT_PROPERTY_NAME' | translate }}</span>
+ <span class="cell header-cell field-input-type">{{ 'IMPLEMENTATION_ARTIFACT_PROPERTY_TYPE' | translate }}</span>
+ <span class="cell header-cell field-input-value">{{ 'IMPLEMENTATION_ARTIFACT_PROPERTY_VALUE' | translate }}</span>
+ </div>
+
+ <div class="empty-msg data-row" *ngIf="!toscaArtifactTypeProperties.length">
+ <div>{{ 'EMPTY_PARAM_TABLE_HEADER' | translate }}</div>
+ </div>
+ <property-param-row
+ *ngFor="let property of toscaArtifactTypeProperties"
+ class="data-row"
+ [artifactProperty]="property"
+ [isPropertyValueValid]="propertyValueValidation">
+ </property-param-row>
+ </div>
+ </div>
</div>
<div class="separator-buttons">
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less
index 8bbed9de02..955720c49d 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less
@@ -27,6 +27,22 @@
padding-top: 12px;
padding-bottom: 20px;
+ .group-with-border {
+ margin: 25px 0;
+ padding: 15px 0;
+ border-top: 1px solid @tlv_color_u;
+ border-bottom: 1px solid @tlv_color_u;
+ .content-row:not(:last-of-type) {
+ padding-bottom: 13px;
+ }
+ }
+
+ .occurrences-label {
+ font-family: @font-opensans-regular;
+ margin-bottom: 19px;
+ font-size: 14px;
+ }
+
.i-sdc-form-label {
font-size: 12px;
}
@@ -175,7 +191,7 @@
}
/deep/ .cell {
- &.field-input-name, &.field-input-value{
+ &.field-input-name, &.field-input-type, &.field-input-value{
flex: 1;
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts
index 1618af4aea..0b0efde1bf 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts
@@ -19,7 +19,7 @@
* ============LICENSE_END=========================================================
*/
-import {Component} from '@angular/core';
+import {Component, EventEmitter, Output} from '@angular/core';
import {UIInterfaceModel} from "../interface-operations.component";
import {
InputOperationParameter,
@@ -27,6 +27,12 @@ import {
IOperationParamsList
} from "../../../../../models/interfaceOperation";
import {TranslateService} from "../../../../shared/translator/translate.service";
+import {IDropDownOption} from "onap-ui-angular/dist/form-elements/dropdown/dropdown-models";
+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";
@Component({
selector: 'operation-handler',
@@ -36,20 +42,32 @@ import {TranslateService} from "../../../../shared/translator/translate.service"
})
export class InterfaceOperationHandlerComponent {
+ @Output('propertyChanged') emitter: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>();
input: {
+ toscaArtifactTypes: Array<DropdownValue>;
selectedInterface: UIInterfaceModel;
selectedInterfaceOperation: InterfaceOperationModel;
validityChangedCallback: Function;
};
interfaceType: string;
+ artifactVersion: string;
+ artifactName: string;
interfaceOperationName: string;
operationToUpdate: InterfaceOperationModel;
inputs: Array<InputOperationParameter> = [];
+ properties: Array<PropertyParamRowComponent> = [];
isLoading: boolean = false;
readonly: boolean;
+ toscaArtifactTypeSelected: string;
+ toscaArtifactTypeProperties: Array<PropertyBEModel> = [];
+
+ toscaArtifactTypes: Array<DropdownValue> = [];
+
+ enableAddArtifactImplementation: boolean;
+
ngOnInit() {
this.interfaceType = this.input.selectedInterface.displayType();
this.operationToUpdate = new InterfaceOperationModel(this.input.selectedInterfaceOperation);
@@ -60,9 +78,82 @@ export class InterfaceOperationHandlerComponent {
listToscaDataDefinition: Array<InputOperationParameter> = [];
}
}
+
this.inputs = this.operationToUpdate.inputs.listToscaDataDefinition;
this.removeImplementationQuote();
this.validityChanged();
+ this.loadInterfaceOperationImplementation();
+ }
+
+ private loadInterfaceOperationImplementation() {
+ this.toscaArtifactTypes = this.input.toscaArtifactTypes;
+ this.artifactVersion = this.operationToUpdate.implementation.artifactVersion;
+ this.artifactName = this.operationToUpdate.implementation.artifactName;
+ this.toscaArtifactTypeProperties = this.operationToUpdate.implementation.properties;
+ this.getArtifactTypesSelected();
+ }
+
+ onDescriptionChange= (value: any): void => {
+ this.operationToUpdate.description = value;
+ }
+
+ onImplementationNameChange(value: any) {
+ this.readonly = true
+ if (value) {
+ let artifact = new ArtifactModel();
+ artifact.artifactName = value;
+ this.operationToUpdate.implementation = artifact;
+ this.enableAddArtifactImplementation = false;
+ this.readonly = false;
+ }
+ }
+
+ onPropertyValueChange = (propertyValue) => {
+ this.emitter.emit(propertyValue);
+ }
+
+ onMarkToAddArtifactToImplementation(event: any) {
+ if (!event) {
+ this.toscaArtifactTypeSelected = undefined;
+ this.artifactVersion = undefined;
+ if (this.operationToUpdate.implementation.artifactType) {
+ this.artifactName = undefined;
+ }
+ this.toscaArtifactTypeProperties = undefined;
+ } else {
+ this.getArtifactTypesSelected();
+ }
+ this.enableAddArtifactImplementation = event;
+ this.validateRequiredField();
+ }
+
+ onSelectToscaArtifactType(type: IDropDownOption) {
+ if (type) {
+ let toscaArtifactType = type.value;
+ let artifact = new ArtifactModel();
+ this.artifactName = undefined;
+ this.artifactVersion = undefined;
+ artifact.artifactType = toscaArtifactType.type;
+ artifact.properties = toscaArtifactType.properties;
+ this.toscaArtifactTypeProperties = artifact.properties;
+ this.toscaArtifactTypeSelected = artifact.artifactType;
+ this.operationToUpdate.implementation = artifact;
+ this.getArtifactTypesSelected();
+ }
+ this.validateRequiredField();
+ }
+
+ onArtifactFileChange(value: any) {
+ if (value) {
+ this.operationToUpdate.implementation.artifactName = value;
+ }
+ this.validateRequiredField();
+ }
+
+ onArtifactVersionChange(value: any) {
+ if (value) {
+ this.operationToUpdate.implementation.artifactVersion = value;
+ }
}
onAddInput(inputOperationParameter?: InputOperationParameter): void {
@@ -73,12 +164,32 @@ export class InterfaceOperationHandlerComponent {
this.validityChanged();
}
+ propertyValueValidation = (propertyValue): void => {
+ this.onPropertyValueChange(propertyValue);
+ this.readonly = !propertyValue.isValid;
+ }
+
onRemoveInput = (inputParam: InputOperationParameter): void => {
let index = this.inputs.indexOf(inputParam);
this.inputs.splice(index, 1);
this.validityChanged();
}
+ 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);
+ }
+ }
+ }
+
private generateUniqueId = (): string => {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
@@ -97,8 +208,24 @@ export class InterfaceOperationHandlerComponent {
}
}
- onDescriptionChange= (value: any): void => {
- this.operationToUpdate.description = value;
+ private getArtifactTypesSelected() {
+ if (this.operationToUpdate.implementation && this.operationToUpdate.implementation.artifactType) {
+ this.artifactName = this.operationToUpdate.implementation.artifactName;
+ this.toscaArtifactTypeSelected = this.operationToUpdate.implementation.artifactType;
+ this.artifactVersion = this.operationToUpdate.implementation.artifactVersion;
+ this.toscaArtifactTypeProperties = this.operationToUpdate.implementation.properties;
+ this.enableAddArtifactImplementation = true;
+ }
+ this.validateRequiredField();
+ }
+
+ validateRequiredField = () => {
+ this.readonly = true;
+ let requiredFieldSelected = this.toscaArtifactTypeSelected && this.artifactName ? true : false;
+ this.input.validityChangedCallback(requiredFieldSelected);
+ if (requiredFieldSelected) {
+ this.readonly = false;
+ }
}
private checkFormValidForSubmit = (): boolean => {
@@ -114,17 +241,8 @@ export class InterfaceOperationHandlerComponent {
return isValid;
}
- private removeImplementationQuote(): void {
- 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);
- }
+ toDropDownOption(val: string) {
+ return { value : val, label: val };
}
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.module.ts b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.module.ts
index deba50aa7d..259530105c 100644
--- a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.module.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.module.ts
@@ -30,11 +30,14 @@ import {SdcUiComponentsModule} from 'onap-ui-angular';
import {UiElementsModule} from '../../../../components/ui/ui-elements.module';
import {InputParamRowComponent} from './input-param-row/input-param-row.component';
import {InterfaceOperationHandlerComponent} from "./interface-operation-handler.component";
+import {PropertyParamRowComponent} from "./property-param-row/property-param-row.component";
+import {PropertyTableModule} from "../../../../components/logic/properties-table/property-table.module";
@NgModule({
declarations: [
InterfaceOperationHandlerComponent,
- InputParamRowComponent
+ InputParamRowComponent,
+ PropertyParamRowComponent
],
imports: [
CommonModule,
@@ -42,9 +45,12 @@ import {InterfaceOperationHandlerComponent} from "./interface-operation-handler.
FormsModule,
FormElementsModule,
TranslateModule,
- UiElementsModule
+ UiElementsModule,
+ PropertyTableModule
+ ],
+ exports: [
+ PropertyParamRowComponent
],
- exports: [],
entryComponents: [
InterfaceOperationHandlerComponent
],
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.html b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.html
new file mode 100644
index 0000000000..ef7b94ccc1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.html
@@ -0,0 +1,44 @@
+<!--
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2021 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ -->
+
+<div class="cell field-input-name">
+ <sdc-input
+ [(value)]="artifactProperty.name"
+ [disabled]="true"
+ testId="interface-operation-input-name">
+ </sdc-input>
+</div>
+
+<div class="cell field-input-type">
+ <sdc-input
+ [(value)]="artifactProperty.type"
+ [disabled]="true"
+ testId="operation-implementation-property-type">
+ </sdc-input>
+</div>
+
+<div class="cell field-input-value">
+ <dynamic-element
+ [(value)]="artifactProperty.value"
+ data-tests-id="operation-implementation-property-value"
+ (elementChanged)="isPropertyValueValid($event)"
+ [type]="artifactProperty ? artifactProperty.type : 'string'">
+ </dynamic-element>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.less b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.less
new file mode 100644
index 0000000000..12eacc6473
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.less
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2021 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+@import '../../../../../../../assets/styles/variables.less';
+
+.remove {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ svg-icon {
+ position: relative;
+ right: -3px;
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+}
+
+.cell {
+ min-height: 50px;
+ padding: 10px;
+ display: flex;
+ align-items: center;
+
+ > * {
+ flex-basis: 100%;
+ }
+
+ /deep/ select {
+ height: 30px;
+ }
+
+ input {
+ height: 30px;
+ border: none;
+ padding-left: 10px;
+ }
+
+ select {
+ width: 100%;
+ }
+
+ &.field-property {
+ &:last-child {
+ flex: 1;
+ }
+
+ .no-properties-error {
+ color: @func_color_q;
+ font-style: italic;
+ }
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.ts b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.ts
new file mode 100644
index 0000000000..6ae75fa5d9
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/property-param-row/property-param-row.component.ts
@@ -0,0 +1,35 @@
+/*
+* ============LICENSE_START=======================================================
+* SDC
+* ================================================================================
+* Copyright (C) 2021 Nordix Foundation. All rights reserved.
+* ================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+* SPDX-License-Identifier: Apache-2.0
+* ============LICENSE_END=========================================================
+*/
+
+import {Component, Input} from '@angular/core';
+import {PropertyOperationParameter} from "../../../../../../models/interfaceOperation";
+
+@Component({
+ selector: 'property-param-row',
+ templateUrl: './property-param-row.component.html',
+ styleUrls: ['./property-param-row.component.less']
+})
+
+export class PropertyParamRowComponent {
+ @Input() artifactProperty: PropertyOperationParameter;
+ @Input() isPropertyValueValid: Function;
+
+}