aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src
diff options
context:
space:
mode:
authoraribeiro <anderson.ribeiro@est.tech>2020-11-19 13:28:43 +0000
committerChristophe Closset <christophe.closset@intl.att.com>2021-01-29 08:22:04 +0000
commit5c1f5756bcb5856e2d8b35e3c6ac206f891f8695 (patch)
tree29a7c4424b3ced8800e5bcacc629c8fff8dd8753 /catalog-ui/src
parent3c957597725f306b4ca06cebfa54fbf0f2622938 (diff)
Add support for updating interface operations
Allows to update interface operations on a component instance. Issue-ID: SDC-3446 Signed-off-by: aribeiro <anderson.ribeiro@est.tech> Signed-off-by: andre.schmid <andre.schmid@est.tech> Change-Id: I6a2c44997c04d9d9ea298e3d0bc971da7b137799
Diffstat (limited to 'catalog-ui/src')
-rw-r--r--catalog-ui/src/app/models/componentsInstances/componentInstance.ts2
-rw-r--r--catalog-ui/src/app/models/inputs.ts2
-rw-r--r--catalog-ui/src/app/models/interfaceOperation.ts109
-rw-r--r--catalog-ui/src/app/ng2/app.module.ts2
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.ts4
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.html2
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.html80
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.less216
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.ts247
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-param-row.component.html44
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-param-row.component.less72
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-param-row.component.ts48
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html86
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less200
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts130
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.module.ts55
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts15
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts12
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.module.ts10
-rw-r--r--catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts31
-rw-r--r--catalog-ui/src/assets/languages/en_US.json4
21 files changed, 1356 insertions, 15 deletions
diff --git a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts
index 2e0c1a59c8..a55cd4f0d1 100644
--- a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts
+++ b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts
@@ -103,6 +103,7 @@ export class ComponentInstance implements IComponentInstance{
public invariantName:string;
public originArchived:boolean;
public directives: string[];
+ public interfaces:any;
constructor(componentInstance?:ComponentInstance) {
@@ -135,6 +136,7 @@ export class ComponentInstance implements IComponentInstance{
this.sourceModelUuid = componentInstance.sourceModelUuid;
this.originArchived = componentInstance.originArchived;
this.directives = componentInstance.directives;
+ this.interfaces = componentInstance.interfaces;
}
}
diff --git a/catalog-ui/src/app/models/inputs.ts b/catalog-ui/src/app/models/inputs.ts
index 49fd16dfaf..562db98168 100644
--- a/catalog-ui/src/app/models/inputs.ts
+++ b/catalog-ui/src/app/models/inputs.ts
@@ -65,6 +65,7 @@ export class InputModel implements IInputModel {
schema:SchemaPropertyGroupModel;
defaultValue:string;
value:string;
+ toscaDefaultValue?: string;
//costom properties
isNew:boolean;
@@ -94,6 +95,7 @@ export class InputModel implements IInputModel {
this.filterTerm = this.name + ' ' + this.description + ' ' + this.type + ' ' + this.componentInstanceName;
this.inputs = input.inputs;
this.properties = input.properties;
+ this.toscaDefaultValue = input.toscaDefaultValue;
}
}
diff --git a/catalog-ui/src/app/models/interfaceOperation.ts b/catalog-ui/src/app/models/interfaceOperation.ts
new file mode 100644
index 0000000000..5c69688745
--- /dev/null
+++ b/catalog-ui/src/app/models/interfaceOperation.ts
@@ -0,0 +1,109 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation
+ * ================================================================================
+ * 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=========================================================
+ */
+
+'use strict';
+
+export class InputOperationParameter {
+ name: string;
+ type: string;
+ inputId: string;
+ toscaDefaultValue?: string;
+
+ constructor(param?: any) {
+ if (param) {
+ this.name = param.name;
+ this.type = param.type;
+ this.inputId = param.inputId;
+ this.toscaDefaultValue = param.toscaDefaultValue;
+ }
+ console.info("InputOperationParameter Constructor: ", param)
+ }
+}
+
+export interface IOperationParamsList {
+ listToscaDataDefinition: Array<InputOperationParameter>;
+}
+
+export class BEInterfaceOperationModel {
+ name: string;
+ description: string;
+ uniqueId: string;
+ inputs: IOperationParamsList;
+ implementation?: InterfaceOperationImplementation;
+
+ constructor(operation?: any) {
+ if (operation) {
+ this.name = operation.name;
+ this.description = operation.description;
+ this.uniqueId = operation.uniqueId;
+ this.inputs = operation.inputs;
+ this.implementation = operation.implementation;
+ }
+ }
+}
+
+export class InterfaceOperationModel extends BEInterfaceOperationModel {
+ interfaceType: string;
+ interfaceId: string;
+ operationType: string;
+ description: string;
+ uniqueId: string;
+ implementation?: InterfaceOperationImplementation;
+ inputParams: IOperationParamsList;
+
+ constructor(operation?: any) {
+ super(operation);
+ if (operation) {
+ this.interfaceId = operation.interfaceId;
+ this.interfaceType = operation.interfaceType;
+ this.description = operation.description;
+ this.operationType = operation.operationType;
+ this.uniqueId = operation.uniqueId;
+ this.inputParams = operation.inputParams;
+ }
+ }
+
+ public displayType(): string {
+ return displayType(this.interfaceType);
+ }
+}
+
+export class InterfaceOperationImplementation {
+ artifactName: string;
+}
+
+export class ComponentInstanceInterfaceModel {
+ type: string;
+ uniqueId: string;
+ operations: Array<InterfaceOperationModel>;
+
+ constructor(interfaceOperation?: any) {
+ if (interfaceOperation) {
+ this.type = interfaceOperation.type;
+ this.uniqueId = interfaceOperation.uniqueId;
+ this.operations = interfaceOperation.operations;
+ }
+ }
+
+ public displayType(): string {
+ return displayType(this.type);
+ }
+}
+
+const displayType = (type:string) => type && type.substr(type.lastIndexOf('.') + 1);
diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts
index b94ba61f75..ac8a9b6eff 100644
--- a/catalog-ui/src/app/ng2/app.module.ts
+++ b/catalog-ui/src/app/ng2/app.module.ts
@@ -96,6 +96,7 @@ import { DeclareListModule } from './pages/properties-assignment/declare-list/de
import { WorkflowServiceNg2 } from './services/workflow.service';
import { ToscaTypesServiceNg2 } from "./services/tosca-types.service";
import {CapabilitiesFilterPropertiesEditorComponentModule} from "./pages/composition/capabilities-filter-properties-editor/capabilities-filter-properties-editor.module";
+import {InterfaceOperationHandlerModule} from "./pages/composition/interface-operatons/operation-creator/interface-operation-handler.module";
declare const __ENV__: string;
@@ -149,6 +150,7 @@ export function configServiceFactory(config: ConfigService, authService: Authent
PluginsModule,
InterfaceOperationModule,
OperationCreatorModule,
+ InterfaceOperationHandlerModule,
ServicePathCreatorModule,
ServicePathsListModule,
ServicePathSelectorModule,
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.ts
index 1b1363e576..d7b997d86a 100644
--- a/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/canvas-zone/zone-instance/zone-instance.component.ts
@@ -66,7 +66,7 @@ export class ZoneInstanceComponent implements OnInit {
}
private setMode = (mode:ZoneInstanceMode, event?:any, afterSaveCallback?:Function):void => {
-
+
if(event){ //prevent event from handle and then repeat event from zone instance
event.stopPropagation();
}
@@ -125,4 +125,4 @@ export class ZoneInstanceComponent implements OnInit {
event.stopPropagation();
};
-} \ No newline at end of file
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.html
index 5a0ca3e43f..9f6a8bcbf9 100644
--- a/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.html
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.component.html
@@ -54,4 +54,4 @@
(assignmentSaveComplete)="zoneAssignmentSaveComplete($event)">
</zone-instance>
</zone-container>
-</div> \ No newline at end of file
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.html b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.html
new file mode 100644
index 0000000000..7567b90365
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.html
@@ -0,0 +1,80 @@
+<!--
+ * ============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="interface-operations">
+ <loader [display]="isLoading" [size]="'large'" [relative]="true"></loader>
+ <div class="operation-list">
+ <div *ngIf="!isListEmpty()">
+ <div class="expand-collapse">
+ <a class="link"
+ [ngClass]="{'disabled': isAllExpanded()}"
+ (click)="collapseAll(false)">{{ 'INTERFACE_EXPAND_ALL' | translate }}
+ </a> |
+ <a class="link"
+ [ngClass]="{'disabled': isAllCollapsed()}"
+ (click)="collapseAll()">
+ {{ 'INTERFACE_COLLAPSE_ALL' | translate }}
+ </a>
+ </div>
+
+ <div class="interface-row" *ngFor="let interface1 of interfaces">
+ <div class="interface-accordion" (click)="interface1.toggleCollapse()">
+ <span
+ class="chevron-container"
+ [ngClass]="{'isCollapsed': interface1.isCollapsed}">
+ <svg-icon
+ name="caret1-down-o"
+ mode="primary"
+ size="small">
+ </svg-icon>
+ </span>
+ <span class="interface-name">{{interface1.displayType()}}</span>
+ </div>
+
+ <div class="generic-table" *ngIf="!interface1.isCollapsed">
+ <div class="header-row table-row">
+ <span
+ class="cell header-cell field-name header-name">
+ {{ 'INTERFACE_HEADER_NAME' | translate }}
+ </span>
+ <span class="cell header-cell field-description header-description">
+ {{ 'INTERFACE_HEADER_DESCRIPTION' | translate }}
+ </span>
+ </div>
+
+ <div class="data-row" *ngFor="let operation of interface1.operations"
+ (click)="onSelectInterfaceOperation(interface1, operation)">
+ <span
+ class="cell field-name">
+ {{operation.name}}
+ </span>
+ <span class="cell field-description"
+ [ngClass]="{'collapsed': operation.isCollapsed}">
+ {{operation.getDescriptionEllipsis()}}
+ <span class="more-or-less link" (click)="operation.toggleCollapsed($event)">
+ {{!operation.isEllipsis ? '' : operation.isCollapsed ? 'More' : 'Less'}}
+ </span>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.less b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.less
new file mode 100644
index 0000000000..1ebfb1fe82
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.less
@@ -0,0 +1,216 @@
+/*-
+ * ============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/override.less';
+@import './../../../../../assets/styles/variables.less';
+
+.interface-operations {
+ font-size: 14px;
+
+ .top-add-btn {
+ position: relative;
+ top: -31px;
+ text-transform: uppercase;
+ font-size: 14px;
+ font-family: @font-opensans-medium;
+ }
+
+ .link {
+ color: @sdcui_color_blue;
+ text-decoration: underline;
+ font-family: @font-opensans-regular;
+
+ &:not(.disabled) {
+ &:not(.empty-list-add-btn) {
+ &:hover {
+ color: @sdcui_color_dark-blue;
+ cursor: pointer;
+ }
+ }
+ }
+ }
+
+ .operation-list {
+ border-top: 1px solid @main_color_o;
+ padding-top: 5px;
+
+ .empty-list-container {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+
+ .empty-list-add-btn {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+
+ border: 1px solid @main_color_o;
+ margin-top: 50px;
+
+ height: 229px;
+ width: 480px;
+
+ &.disabled {
+ pointer-events: none;
+ }
+
+ &:hover {
+ &:not(.disabled) {
+ border: 1px solid @sdcui_color_blue;
+ cursor: pointer;
+ }
+ }
+
+ .button-text {
+ margin-top: 9px;
+ font-family: @font-opensans-medium;
+ font-size: 16px;
+ text-transform: uppercase;
+ color: @sdcui_color_blue;
+ }
+ }
+ }
+
+ .expand-collapse {
+ margin-top: 4px;
+ margin-bottom: 18px;
+ color: @sdcui_color_light-gray;
+ }
+
+ .interface-row {
+ width: 100%;
+ margin-top: 13px;
+ border-bottom: 1px solid @main_color_o;
+ padding-left: 4px;
+ min-height: 37px;
+
+
+ .interface-accordion {
+ cursor: pointer;
+
+ .chevron-container {
+ position: relative;
+ margin-right: 5px;
+
+ &.isCollapsed {
+ right: -6px;
+ top: 0;
+ * {
+ transform: rotate(270deg);
+ }
+ }
+ &:not(.isCollapsed) {
+ top: 6px;
+ }
+ * {
+ &:hover {
+ cursor: pointer;
+ }
+ }
+ }
+ .interface-name {
+ font-size: 18px;
+ font-family: @font-opensans-bold;
+ margin-bottom: 15px;
+ }
+ }
+
+ .generic-table {
+ margin-bottom: 24px;
+ margin-top: 10px;
+ margin-left: 22px;
+ font-size: 14px;
+
+ .header-row, .data-row {
+ .cell {
+ &.field-description {
+ flex: 2.5;
+ }
+
+ &.field-actions {
+ flex-basis: 72px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+ }
+ }
+
+ .header-row {
+ .cell {
+ background: @sdcui_color_silver;
+
+ &.field-actions {
+ font-size: 10px;
+ }
+ }
+ }
+
+ .data-row {
+ cursor: pointer;
+
+ &:hover {
+ background: @sdcui_color_light-silver;
+
+ .cell {
+ &.field-name {
+ color: @sdcui_color_dark-blue;
+ }
+ }
+ }
+
+ &:not(:hover) {
+ .field-actions {
+ visibility: hidden;
+ }
+ }
+
+ .cell {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+
+ &.field-description {
+ &:not(.collapsed) {
+ white-space: normal;
+ }
+ &.collapsed {
+ text-overflow: clip;
+ }
+ .more-or-less {
+ margin-left: 5px;
+ }
+ }
+
+ &.field-actions {
+ .delete-action {
+ position: relative;
+ top: 2px;
+ }
+ }
+ }
+
+ }
+ }
+
+ }
+ }
+}
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
new file mode 100644
index 0000000000..304fbcec3e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/interface-operations.component.ts
@@ -0,0 +1,247 @@
+/*
+* ============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, ComponentRef, 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';
+import { ModalComponent } from 'app/ng2/components/ui/modal/modal.component';
+import {
+ Component as TopologyTemplate
+} from "../../../../models/components/component";
+import {PluginsService} from "app/ng2/services/plugins.service";
+import {SelectedComponentType} from "../common/store/graph.actions";
+
+import {WorkspaceService} from "../../workspace/workspace.service";
+import {
+ ComponentInstanceInterfaceModel,
+ InterfaceOperationModel
+} from "../../../../models/interfaceOperation";
+import {
+ InterfaceOperationHandlerComponent
+} from "./operation-creator/interface-operation-handler.component";
+
+import {
+ ButtonModel,
+ ComponentMetadata,
+ InterfaceModel,
+ InputBEModel,
+ ModalModel,
+ ComponentInstance
+} from 'app/models';
+
+export class UIInterfaceOperationModel extends InterfaceOperationModel {
+ isCollapsed: boolean = true;
+ isEllipsis: boolean;
+ MAX_LENGTH = 75;
+ _description: string;
+
+ constructor(operation: InterfaceOperationModel) {
+ super(operation);
+
+ if (!operation.description) {
+ this.description = '';
+ }
+
+ if (this.description.length > this.MAX_LENGTH) {
+ this.isEllipsis = true;
+ } else {
+ this.isEllipsis = false;
+ }
+ }
+
+ getDescriptionEllipsis(): string {
+ if (this.isCollapsed && this.description.length > this.MAX_LENGTH) {
+ return this.description.substr(0, this.MAX_LENGTH - 3) + '...';
+ }
+ return this.description;
+ }
+
+ toggleCollapsed(e) {
+ e.stopPropagation();
+ this.isCollapsed = !this.isCollapsed;
+ }
+}
+
+class ModalTranslation {
+ EDIT_TITLE: string;
+ CANCEL_BUTTON: string;
+ SAVE_BUTTON: string;
+
+ constructor(private TranslateService: TranslateService) {
+ this.TranslateService.languageChangedObservable.subscribe(lang => {
+ this.EDIT_TITLE = this.TranslateService.translate('INTERFACE_EDIT_TITLE');
+ this.CANCEL_BUTTON = this.TranslateService.translate("INTERFACE_CANCEL_BUTTON");
+ this.SAVE_BUTTON = this.TranslateService.translate("INTERFACE_SAVE_BUTTON");
+ });
+ }
+}
+
+export class UIInterfaceModel extends ComponentInstanceInterfaceModel {
+ isCollapsed: boolean = false;
+
+ constructor(interf?: any) {
+ super(interf);
+ this.operations = _.map(
+ this.operations,
+ (operation) => new UIInterfaceOperationModel(operation)
+ );
+ }
+
+ toggleCollapse() {
+ this.isCollapsed = !this.isCollapsed;
+ }
+}
+
+@Component({
+ selector: 'app-interface-operations',
+ templateUrl: './interface-operations.component.html',
+ styleUrls: ['./interface-operations.component.less'],
+ providers: [ModalService, TranslateService]
+})
+export class InterfaceOperationsComponent {
+ interfaces: UIInterfaceModel[];
+ selectedOperation: InterfaceOperationModel;
+ inputs: Array<InputBEModel>;
+ isLoading: boolean;
+ interfaceTypes: { [interfaceType: string]: string[] };
+ topologyTemplate: TopologyTemplate;
+ componentMetaData: ComponentMetadata;
+ componentInstanceSelected: ComponentInstance;
+ modalInstance: ComponentRef<ModalComponent>;
+ modalTranslation: ModalTranslation;
+ componentInstancesInterfaces: Map<string, InterfaceModel[]>;
+
+ @Input() component: ComponentInstance;
+ @Input() readonly: boolean;
+ @Input() enableMenuItems: Function;
+ @Input() disableMenuItems: Function;
+ @Input() componentType: SelectedComponentType;
+
+
+ constructor(
+ private TranslateService: TranslateService,
+ private PluginsService: PluginsService,
+ private topologyTemplateService: TopologyTemplateService,
+ private modalServiceNg2: ModalService,
+ private workspaceService: WorkspaceService,
+ ) {
+ this.modalTranslation = new ModalTranslation(TranslateService);
+ }
+
+ ngOnInit(): void {
+ this.componentMetaData = this.workspaceService.metadata;
+ this.loadComponentInstances();
+ }
+
+ private loadComponentInstances() {
+ this.isLoading = true;
+ this.topologyTemplateService.getComponentInstances(this.componentMetaData.componentType, this.componentMetaData.uniqueId)
+ .subscribe((response) => {
+ this.componentInstanceSelected = response.componentInstances.find(ci => ci.uniqueId === this.component.uniqueId);
+ this.initComponentInstanceInterfaceOperations();
+ this.isLoading = false;
+ });
+ }
+
+ private initComponentInstanceInterfaceOperations() {
+ this.initInterfaces(this.componentInstanceSelected.interfaces);
+ this.sortInterfaces();
+ }
+
+ private initInterfaces(interfaces: InterfaceModel[]): void {
+ this.interfaces = _.map(interfaces, (interfaceModel) => new UIInterfaceModel(interfaceModel));
+ }
+
+ private sortInterfaces(): void {
+ this.interfaces = _.filter(this.interfaces, (interf) => interf.operations && interf.operations.length > 0); // remove empty interfaces
+ this.interfaces.sort((a, b) => a.type.localeCompare(b.type)); // sort interfaces alphabetically
+ _.forEach(this.interfaces, (interf) => {
+ interf.operations.sort((a, b) => a.name.localeCompare(b.name)); // sort operations alphabetically
+ });
+ }
+
+ collapseAll(value: boolean = true): void {
+ _.forEach(this.interfaces, (interf) => {
+ interf.isCollapsed = value;
+ });
+ }
+
+ isAllCollapsed(): boolean {
+ return _.every(this.interfaces, (interf) => interf.isCollapsed);
+ }
+
+ isAllExpanded(): boolean {
+ return _.every(this.interfaces, (interf) => !interf.isCollapsed);
+ }
+
+ isListEmpty(): boolean {
+ return _.filter(
+ this.interfaces,
+ (interf) => interf.operations && interf.operations.length > 0
+ ).length === 0;
+ }
+
+ private enableOrDisableSaveButton = (): boolean => {
+ return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
+ }
+
+ onSelectInterfaceOperation(interfaceModel: UIInterfaceModel, operation: InterfaceOperationModel) {
+ const cancelButton: ButtonModel = new ButtonModel(this.modalTranslation.CANCEL_BUTTON, 'outline white', this.cancelAndCloseModal);
+ const saveButton: ButtonModel = new ButtonModel(this.modalTranslation.SAVE_BUTTON, 'blue', () =>
+ this.updateInterfaceOperation(), this.enableOrDisableSaveButton);
+ const modalModel: ModalModel = new ModalModel('l', this.modalTranslation.EDIT_TITLE, '', [saveButton, cancelButton], 'custom');
+ this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
+
+ this.modalServiceNg2.addDynamicContentToModal(
+ this.modalInstance,
+ InterfaceOperationHandlerComponent,
+ {
+ selectedInterface: interfaceModel,
+ selectedInterfaceOperation: operation,
+ validityChangedCallback: this.enableOrDisableSaveButton
+ }
+ );
+ this.modalInstance.instance.open();
+ }
+
+ private cancelAndCloseModal = () => {
+ this.loadComponentInstances();
+ return this.modalServiceNg2.closeCurrentModal();
+ }
+
+ private updateInterfaceOperation() {
+ this.isLoading = true;
+ let operationUpdated = this.modalInstance.instance.dynamicContent.instance.operationToUpdate;
+ this.topologyTemplateService.updateComponentInstanceInterfaceOperation(
+ this.componentMetaData.uniqueId,
+ this.componentMetaData.componentType,
+ this.componentInstanceSelected.uniqueId,
+ operationUpdated)
+ .subscribe((updatedComponentInstance: ComponentInstance) => {
+ this.componentInstanceSelected = new ComponentInstance(updatedComponentInstance);
+ this.initComponentInstanceInterfaceOperations();
+ });
+ this.modalServiceNg2.closeCurrentModal();
+ this.isLoading = false;
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-param-row.component.html b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-param-row.component.html
new file mode 100644
index 0000000000..80aceeadda
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-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)]="input.name"
+ (valueChange)="onChange()">
+ </sdc-input>
+</div>
+
+<div class="cell field-input-value">
+ <sdc-input
+ [(value)]="input.toscaDefaultValue"
+ (valueChange)="onChange()">
+ </sdc-input>
+
+</div>
+
+<div class="cell remove" *ngIf="!readonly">
+ <svg-icon
+ name="trash-o"
+ mode="info"
+ size="small"
+ (click)="onRemoveInput(input)"
+ [clickable]="true">
+ </svg-icon>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-param-row.component.less b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-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/input-param-row/input-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/input-param-row/input-param-row.component.ts b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-param-row.component.ts
new file mode 100644
index 0000000000..48bb804173
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-param-row.component.ts
@@ -0,0 +1,48 @@
+/*
+* ============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 {InputOperationParameter} from "../../../../../../models/interfaceOperation";
+
+@Component({
+ selector: 'input-param-row',
+ templateUrl: './input-param-row.component.html',
+ styleUrls: ['./input-param-row.component.less']
+})
+
+export class InputParamRowComponent {
+ @Input() input: InputOperationParameter;
+ @Input() onRemoveInput: Function;
+ @Input() readonly: boolean;
+ @Input() validityChanged: Function;
+
+ constructor() {
+ }
+
+ ngOnInit() {
+ this.validityChanged();
+ }
+
+ onChange() {
+ this.validityChanged();
+ }
+
+}
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
new file mode 100644
index 0000000000..cd2d6063c1
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html
@@ -0,0 +1,86 @@
+<!--
+ * ============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="operation-handler">
+ <loader [display]="isLoading" [size]="'large'" [relative]="true"></loader>
+
+ <form class="w-sdc-form">
+
+ <div class="side-by-side">
+ <div class="form-item">
+ <sdc-input
+ label="{{ 'OPERATION_INTERFACE_TYPE' | translate }}"
+ [(value)]="interfaceType"
+ [disabled]="true">
+ </sdc-input>
+ </div>
+
+ <div class="form-item">
+ <sdc-input
+ label="{{ 'OPERATION_NAME' | translate }}"
+ [(value)]="operationToUpdate.name"
+ [disabled]="true">
+ </sdc-input>
+ </div>
+ </div>
+
+ <div class="i-sdc-form-item">
+ <sdc-input
+ label="{{'OPERATION_DESCRIPTION' | translate}}"
+ [(value)]="operationToUpdate.description"
+ (valueChange)="onDescriptionChange($event)">
+ </sdc-input>
+ </div>
+
+ <div class="i-sdc-form-item">
+ <sdc-input
+ label="{{'IMPLEMENTATION_NAME' | translate}}"
+ [(value)]="operationToUpdate.implementation.artifactName">
+ </sdc-input>
+ </div>
+
+ <div class="separator-buttons">
+ <tab tabTitle="Inputs"></tab>
+ <a class="add-param-link add-btn"
+ [ngClass]="{'disabled': readonly}"
+ (click)="onAddInput()">{{'OPERATION_ADD_INPUT' | translate}}
+ </a>
+ </div>
+
+ <div class="generic-table">
+ <div class="header-row table-row">
+ <span class="cell header-cell field-input-name">{{ 'OPERATION_PARAM_NAME' | translate }}</span>
+ <span class="cell header-cell field-input-value">{{ 'OPERATION_INPUT_VALUE' | translate }}</span>
+ <span class="cell header-cell remove">●●●</span>
+ </div>
+ <div class="empty-msg data-row" *ngIf="!inputs.length">
+ <div>{{ 'OPERATION_INPUT_EMPTY' | translate }}</div>
+ </div>
+ <input-param-row
+ *ngFor="let inputParameter of inputs"
+ class="data-row"
+ [input]="inputParameter"
+ [onRemoveInput]="onRemoveInput"
+ [validityChanged]="validityChanged">
+ </input-param-row>
+ </div>
+
+ </form>
+</div>
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
new file mode 100644
index 0000000000..8bbed9de02
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.less
@@ -0,0 +1,200 @@
+/*-
+ * ============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';
+@import '../../../../../../assets/styles/override.less';
+
+.operation-handler {
+ font-family: @font-opensans-regular;
+ user-select: none;
+ padding-top: 12px;
+ padding-bottom: 20px;
+
+ .i-sdc-form-label {
+ font-size: 12px;
+ }
+
+ .w-sdc-form .i-sdc-form-item {
+ margin-bottom: 15px;
+ }
+
+ textarea {
+ min-height: 74px;
+ margin-bottom: 18px;
+ }
+
+ /deep/ .sdc-dropdown__component-container {
+ .sdc-dropdown__header {
+ height: 38px;
+ line-height: 35px;
+
+ svg-icon {
+ margin: 13px 6px;
+ }
+ }
+ }
+
+ /deep/ .sdc-input {
+ margin-bottom: 0;
+
+ .sdc-input__input {
+ height: 38px;
+ }
+ }
+
+ .side-by-side {
+ display: flex;
+
+ .form-item {
+ flex: 1;
+
+ &:first-child {
+ margin-right: 14px;
+ flex-basis: 37%;
+ flex-grow: 0;
+ flex-shrink: 0;
+ }
+
+ &:nth-child(3) {
+ margin-left: 14px;
+ flex: 0.4;
+ }
+
+ .i-sdc-form-file-upload {
+ height: 37px;
+ margin-bottom: 0;
+
+ .i-sdc-form-file-name {
+ padding: 8px 10px;
+ }
+
+ .i-sdc-form-file-upload-x-btn {
+ top: 13px;
+ }
+
+ .file-upload-browse-btn {
+ height: 100%;
+ padding: 7px 6px;
+ z-index: 1;
+ }
+ }
+
+ }
+ }
+
+ .archive-warning {
+ font-family: @font-opensans-bold;
+ color: @main_color_i;
+ }
+
+ .no-workflow-warning {
+ font-family: @font-opensans-bold;
+ color: @sdcui_color_red;
+ float: right;
+ }
+
+ .input-param-title {
+ font-size: 16px;
+ text-transform: uppercase;
+ }
+
+ .separator-buttons {
+ display: flex;
+ justify-content: space-between;
+ margin-top: 10px;
+
+ .add-param-link {
+ &:not(.disabled):hover {
+ cursor: pointer;
+ }
+ }
+
+ .tab {
+ width: 84px;
+ text-align: center;
+ }
+ }
+
+ .generic-table {
+ max-height: 244px;
+ min-height: 91px;
+ background: @main_color_p;
+
+ .header-row .header-cell {
+ .info-icon {
+ float: right;
+ position: relative;
+ top: 2px;
+ }
+ /deep/ .tooltip-inner {
+ padding: 2px;
+ max-width: 270px;
+ font-size: 11px;
+ }
+ &.remove {
+ padding: 10px;
+ font-size: 10px;
+ }
+ }
+
+ .data-row {
+ &.empty-msg {
+ .bold-message {
+ font-family: @font-opensans-bold;
+ }
+
+ :first-child {
+ &:not(:only-child) {
+ margin: 6px 0;
+ }
+ }
+
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 14px;
+ }
+ }
+
+ /deep/ .cell {
+ &.field-input-name, &.field-input-value{
+ flex: 1;
+ }
+
+ &.field-property {
+ &, &:last-child {
+ flex: 1;
+ }
+ }
+
+ &.field-mandatory {
+ flex: 0.5;
+ text-align: center;
+ }
+
+ &.remove {
+ min-width: 40px;
+ max-width: 40px;
+ }
+ }
+
+ }
+}
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
new file mode 100644
index 0000000000..1618af4aea
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.ts
@@ -0,0 +1,130 @@
+/*
+* ============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} from '@angular/core';
+import {UIInterfaceModel} from "../interface-operations.component";
+import {
+ InputOperationParameter,
+ InterfaceOperationModel,
+ IOperationParamsList
+} from "../../../../../models/interfaceOperation";
+import {TranslateService} from "../../../../shared/translator/translate.service";
+
+@Component({
+ selector: 'operation-handler',
+ templateUrl: './interface-operation-handler.component.html',
+ styleUrls: ['./interface-operation-handler.component.less'],
+ providers: [TranslateService]
+})
+
+export class InterfaceOperationHandlerComponent {
+
+ input: {
+ selectedInterface: UIInterfaceModel;
+ selectedInterfaceOperation: InterfaceOperationModel;
+ validityChangedCallback: Function;
+ };
+
+ interfaceType: string;
+ interfaceOperationName: string;
+ operationToUpdate: InterfaceOperationModel;
+ inputs: Array<InputOperationParameter> = [];
+ isLoading: boolean = false;
+ readonly: boolean;
+
+ ngOnInit() {
+ this.interfaceType = this.input.selectedInterface.displayType();
+ this.operationToUpdate = new InterfaceOperationModel(this.input.selectedInterfaceOperation);
+ this.operationToUpdate.interfaceId = this.input.selectedInterface.uniqueId;
+ this.operationToUpdate.interfaceType = this.input.selectedInterface.type;
+ if (!this.operationToUpdate.inputs) {
+ this.operationToUpdate.inputs = new class implements IOperationParamsList {
+ listToscaDataDefinition: Array<InputOperationParameter> = [];
+ }
+ }
+ this.inputs = this.operationToUpdate.inputs.listToscaDataDefinition;
+ this.removeImplementationQuote();
+ this.validityChanged();
+ }
+
+ onAddInput(inputOperationParameter?: InputOperationParameter): void {
+ let newInput = new InputOperationParameter(inputOperationParameter)
+ newInput.type = "string";
+ newInput.inputId = this.generateUniqueId();
+ this.inputs.push(newInput);
+ this.validityChanged();
+ }
+
+ 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));
+ }
+ return result;
+ }
+
+ validityChanged = () => {
+ let validState = this.checkFormValidForSubmit();
+ this.input.validityChangedCallback(validState);
+ if (validState) {
+ this.readonly = false;
+ }
+ }
+
+ onDescriptionChange= (value: any): void => {
+ this.operationToUpdate.description = value;
+ }
+
+ private checkFormValidForSubmit = (): boolean => {
+ return this.operationToUpdate.name && this.isParamsValid();
+ }
+
+ private isParamsValid = (): boolean => {
+ const isInputValid = (input) => input.name && input.inputId;
+ const isValid = this.inputs.every(isInputValid);
+ if (!isValid) {
+ this.readonly = true;
+ }
+ 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);
+ }
+ }
+
+}
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
new file mode 100644
index 0000000000..deba50aa7d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.module.ts
@@ -0,0 +1,55 @@
+/*
+* ============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 {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+
+import {FormsModule} from "@angular/forms";
+import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
+import {TranslateModule} from "app/ng2/shared/translator/translate.module";
+
+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";
+
+@NgModule({
+ declarations: [
+ InterfaceOperationHandlerComponent,
+ InputParamRowComponent
+ ],
+ imports: [
+ CommonModule,
+ SdcUiComponentsModule,
+ FormsModule,
+ FormElementsModule,
+ TranslateModule,
+ UiElementsModule
+ ],
+ exports: [],
+ entryComponents: [
+ InterfaceOperationHandlerComponent
+ ],
+ providers: []
+})
+
+export class InterfaceOperationHandlerModule {
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts
index 1761bfdd03..6d96764b1c 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts
@@ -8,7 +8,7 @@ import { Service } from '../../../../models/components/service';
import { Resource } from '../../../../models/components/resource';
import { GroupInstance } from '../../../../models/graph/zones/group-instance';
import { PolicyInstance } from '../../../../models/graph/zones/policy-instance';
-import { ArtifactGroupType, ResourceType } from '../../../../utils/constants';
+import { ArtifactGroupType } from '../../../../utils/constants';
import { WorkspaceState } from '../../../store/states/workspace.state';
import { CompositionPanelComponent } from './composition-panel.component';
import { ArtifactsTabComponent } from './panel-tabs/artifacts-tab/artifacts-tab.component';
@@ -19,6 +19,7 @@ import { PolicyTargetsTabComponent } from './panel-tabs/policy-targets-tab/polic
import { PropertiesTabComponent } from './panel-tabs/properties-tab/properties-tab.component';
import { ReqAndCapabilitiesTabComponent } from './panel-tabs/req-capabilities-tab/req-capabilities-tab.component';
import {SubstitutionFilterTabComponent} from "./panel-tabs/substitution-filter-tab/substitution-filter-tab.component";
+import {InterfaceOperationsComponent} from "../interface-operatons/interface-operations.component";
describe('composition-panel component', () => {
@@ -61,7 +62,13 @@ describe('composition-panel component', () => {
},
inputs: {titleIcon: 'inputs-o', component: PropertiesTabComponent, input: {title: 'Inputs'}, isActive: false, tooltipText: 'Inputs'},
settings: {titleIcon: 'settings-o', component: PropertiesTabComponent, input: {}, isActive: false, tooltipText: 'Settings'},
-
+ interfaceOperations: {
+ titleIcon: 'composition-o',
+ component: InterfaceOperationsComponent,
+ input: {title: 'Interface Operations'},
+ isActive: false,
+ tooltipText: 'Interface Operations'
+ }
};
beforeEach(
@@ -157,17 +164,17 @@ describe('composition-panel component', () => {
fixture.componentInstance.store.select = jest.fn(() => Observable.of(selectedComponent));
fixture.componentInstance.selectedComponentIsServiceProxyInstance = jest.fn(() => true);
- // const pnfMock = Mock.of<Service>({ isResource : () => false });
fixture.componentInstance.topologyTemplate = selectedComponent;
// Call ngOnInit
fixture.componentInstance.ngOnInit();
// Expect that
- expect (fixture.componentInstance.tabs.length).toBe(6);
+ expect (fixture.componentInstance.tabs.length).toBe(7);
expect (fixture.componentInstance.tabs[0]).toEqual(tabs.infoTab);
expect (fixture.componentInstance.tabs[1]).toEqual(tabs.properties);
expect (fixture.componentInstance.tabs[2]).toEqual(tabs.reqAndCapabilities);
+ expect (fixture.componentInstance.tabs[6]).toEqual(tabs.interfaceOperations);
});
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts
index 2fce002844..2ef4e7c9a9 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts
@@ -39,6 +39,7 @@ import { CompositionStateModel, GraphState } from '../common/store/graph.state';
import { ServiceConsumptionTabComponent } from './panel-tabs/service-consumption-tab/service-consumption-tab.component';
import { ServiceDependenciesTabComponent } from './panel-tabs/service-dependencies-tab/service-dependencies-tab.component';
import {SubstitutionFilterTabComponent} from "./panel-tabs/substitution-filter-tab/substitution-filter-tab.component";
+import {InterfaceOperationsComponent} from "../interface-operatons/interface-operations.component";
const tabs = {
infoTab : {titleIcon: 'info-circle', component: InfoTabComponent, input: {}, isActive: true, tooltipText: 'Information'},
@@ -55,7 +56,8 @@ const tabs = {
settings: {titleIcon: 'settings-o', component: PropertiesTabComponent, input: {}, isActive: false, tooltipText: 'Settings'},
consumption: {titleIcon: 'api-o', component: ServiceConsumptionTabComponent, input: {title: 'OPERATION CONSUMPTION'}, isActive: false, tooltipText: 'Service Consumption'},
dependencies: {titleIcon: 'archive', component: ServiceDependenciesTabComponent, input: {title: 'DIRECTIVES AND NODE FILTER'}, isActive: false, tooltipText: 'Service Dependencies'},
- substitutionFilter: {titleIcon: 'composition-o', component: SubstitutionFilterTabComponent, input: {title: 'SUBSTITUTION FILTER'}, isActive: false, tooltipText: 'Substitution Filter'}
+ substitutionFilter: {titleIcon: 'composition-o', component: SubstitutionFilterTabComponent, input: {title: 'SUBSTITUTION FILTER'}, isActive: false, tooltipText: 'Substitution Filter'},
+ interfaceOperations: {titleIcon: 'composition-o', component: InterfaceOperationsComponent, input: {title: 'Interface Operations'}, isActive: false, tooltipText: 'Interface Operations'}
};
@Component({
@@ -86,6 +88,12 @@ export class CompositionPanelComponent {
});
}
+
+ onRightClick(selectedComponent: any) {
+ console.info("onRightClick", selectedComponent)
+ return false;
+ }
+
ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
@@ -151,8 +159,10 @@ export class CompositionPanelComponent {
if (component.isService() && (this.selectedComponentIsServiceProxyInstance() || this.selectedComponentIsServiceSubstitutionInstance())) {
this.tabs.push(tabs.consumption);
this.tabs.push(tabs.dependencies);
+ this.tabs.push(tabs.interfaceOperations);
} else if (component.isResource() && this.isComponentInstanceSelected()) {
this.tabs.push(tabs.dependencies);
+ this.tabs.push(tabs.interfaceOperations);
}
}
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.module.ts b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.module.ts
index a89db21b04..595ee21089 100644
--- a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.module.ts
+++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.module.ts
@@ -49,7 +49,7 @@ import { ServiceDependenciesModule } from "../../../components/logic/service-dep
import { ServiceConsumptionModule } from "../../../components/logic/service-consumption/service-consumption.module";
import {SubstitutionFilterTabComponent} from "./panel-tabs/substitution-filter-tab/substitution-filter-tab.component";
import {SubstitutionFilterModule} from "../../../components/logic/substitution-filter/substitution-filter.module";
-
+import {InterfaceOperationsComponent} from "../interface-operatons/interface-operations.component";
@NgModule({
@@ -67,7 +67,8 @@ import {SubstitutionFilterModule} from "../../../components/logic/substitution-f
ServiceDependenciesTabComponent,
SubstitutionFilterTabComponent,
RequirementListComponent,
- EnvParamsComponent
+ EnvParamsComponent,
+ InterfaceOperationsComponent,
],
imports: [
GlobalPipesModule,
@@ -81,7 +82,7 @@ import {SubstitutionFilterModule} from "../../../components/logic/substitution-f
NgxDatatableModule,
ServiceDependenciesModule,
ServiceConsumptionModule,
- SubstitutionFilterModule
+ SubstitutionFilterModule,
// EnvParamsModule
],
entryComponents: [
@@ -98,7 +99,8 @@ import {SubstitutionFilterModule} from "../../../components/logic/substitution-f
SubstitutionFilterTabComponent,
RequirementListComponent,
PanelTabComponent,
- EnvParamsComponent
+ EnvParamsComponent,
+ InterfaceOperationsComponent
],
exports: [
CompositionPanelComponent
diff --git a/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
index 492acdc1d6..953f0a1960 100644
--- a/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
+++ b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
@@ -35,7 +35,7 @@ import {
PropertyModel,
IFileDownload,
AttributeModel,
- Capability, Requirement
+ Capability, Requirement, BEOperationModel, InterfaceModel
} from "app/models";
import {ArtifactGroupType, COMPONENT_FIELDS} from "app/utils";
import {ComponentGenericResponse} from "../responses/component-generic-response";
@@ -65,6 +65,11 @@ import { PolicyInstance } from "../../../models/graph/zones/policy-instance";
import { PropertyBEModel } from "../../../models/properties-inputs/property-be-model";
import {map} from "rxjs/operators";
import {CapabilitiesConstraintObject} from "../../components/logic/capabilities-constraint/capabilities-constraint.component";
+import {
+ BEInterfaceOperationModel,
+ ComponentInstanceInterfaceModel,
+ InterfaceOperationModel
+} from "../../../models/interfaceOperation";
/* we need to use this service from now, we will remove component.service when we finish remove the angular1.
The service is duplicated since we can not use downgrades service with NGXS*/
@@ -108,8 +113,8 @@ export class TopologyTemplateService {
[COMPONENT_FIELDS.COMPONENT_INSTANCES, COMPONENT_FIELDS.COMPONENT_POLICIES, COMPONENT_FIELDS.COMPONENT_NON_EXCLUDED_GROUPS]);
}
- getComponentResourceInstances(component: Component): Observable<ComponentGenericResponse> {
- return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES]);
+ getComponentInstances(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_INSTANCES]);
}
getComponentInputs(component: Component): Observable<ComponentGenericResponse> {
@@ -478,6 +483,7 @@ export class TopologyTemplateService {
}
protected getComponentDataByFieldsName(componentType: string, componentId: string, fields: string[]): Observable<ComponentGenericResponse> {
+ console.info("Topology template -> getComponentDataByFieldsName with id:", componentId)
let params: HttpParams = new HttpParams();
_.forEach(fields, (field: string): void => {
params = params.append(API_QUERY_PARAMS.INCLUDE, field);
@@ -485,6 +491,7 @@ export class TopologyTemplateService {
// tslint:disable-next-line:object-literal-shorthand
return this.http.get<ComponentGenericResponse>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/filteredDataByParams', {params: params})
.map((res) => {
+ console.info("Topology template -> getComponentDataByFieldsName response:", res);
return componentType === ComponentType.SERVICE ? new ServiceGenericResponse().deserialize(res) :
new ComponentGenericResponse().deserialize(res);
});
@@ -564,4 +571,22 @@ export class TopologyTemplateService {
.pipe(map(response => response.directives));
}
+ updateComponentInstanceInterfaceOperation(componentMetaDataId: string,
+ componentMetaDataType: string,
+ componentInstanceId: string,
+ operation: InterfaceOperationModel): Observable<ComponentInstance> {
+ const operationList = {
+ interfaces: {
+ [operation.interfaceType]: {
+ type: operation.interfaceType,
+ operations: {
+ [operation.name]: new BEInterfaceOperationModel(operation)
+ }
+ }
+ }
+ };
+ return this.http.put<ComponentInstance>(this.baseUrl + this
+ .getServerTypeUrl(componentMetaDataType) + componentMetaDataId + '/componentInstance/' + componentInstanceId + '/interfaceOperation', operationList);
+ }
+
}
diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json
index cc33b36db2..7cc6d554fe 100644
--- a/catalog-ui/src/assets/languages/en_US.json
+++ b/catalog-ui/src/assets/languages/en_US.json
@@ -468,6 +468,7 @@
"OPERATION_INTERFACE_TYPE": "Interface Name",
"OPERATION_NAME": "Operation Name",
"OPERATION_IMPLEMENTATION": "Implementation",
+ "IMPLEMENTATION_NAME": "Implementation Name",
"OPERATION_DESCRIPTION": "Description",
"OPERATION_ARTIFACT": "Workflow Artifact",
"OPERATION_WORKFLOW_ASSIGNMENT": "Workflow Assignment",
@@ -482,6 +483,9 @@
"OPERATION_PARAM_VALUE": "Value",
"OPERATION_PARAM_PROPERTY": "Property",
"OPERATION_PARAM_MANDATORY": "Mandatory",
+ "OPERATION_INPUT_EMPTY": "No Input Data",
+ "OPERATION_INPUT_VALUE": "Value",
+ "OPERATION_ADD_INPUT": "Add Input",
"OPERATION_ADD": "Add",
"OPERATION_ADD1": "Add Operation",
"OPERATION_CANCEL": "Cancel",