View Interface definition on VFC

Add Interface support to VFC view UI

Issue-ID: SDC-3850
Signed-off-by: aribeiro <anderson.ribeiro@est.tech>
Change-Id: Icd195c939af39d40ae8c617e740323dd3e70fc15
diff --git a/catalog-ui/src/app/app.ts b/catalog-ui/src/app/app.ts
index 87930fd..ffa4389 100644
--- a/catalog-ui/src/app/app.ts
+++ b/catalog-ui/src/app/app.ts
@@ -512,6 +512,18 @@
     );
 
     $stateProvider.state(
+        States.WORKSPACE_INTERFACE_DEFINITION, {
+          url: 'interfaceDefinition',
+          parent: 'workspace',
+          controller: viewModelsModuleName + '.InterfaceDefinitionViewModel',
+          templateUrl: './view-models/workspace/tabs/interface-definition/interface-definition-view.html',
+          data: {
+            bodyClass: 'interfaceDefinition'
+          }
+        }
+    );
+
+    $stateProvider.state(
         'workspace.plugins', {
           url: 'plugins/*path',
           parent: 'workspace',
diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts
index 270a764..7719f73 100644
--- a/catalog-ui/src/app/modules/directive-module.ts
+++ b/catalog-ui/src/app/modules/directive-module.ts
@@ -96,6 +96,7 @@
 import {ReqAndCapabilitiesComponent} from "../ng2/pages/workspace/req-and-capabilities/req-and-capabilities.component";
 import {DistributionComponent} from '../ng2/pages/workspace/disribution/distribution.component';
 import {AttributesOutputsComponent} from "../ng2/pages/attributes-outputs/attributes-outputs.page.component";
+import {InterfaceDefinitionComponent} from "../ng2/pages/interface-definition/interface-definition.page.component";
 
 let moduleName: string = 'Sdc.Directives';
 let directiveModule: ng.IModule = angular.module(moduleName, []);
@@ -245,6 +246,12 @@
   outputs: []
 }) as angular.IDirectiveFactory);
 
+directiveModule.directive('interfaceDefinition', downgradeComponent({
+  component: InterfaceDefinitionComponent,
+  inputs: ['component', 'readonly'],
+  outputs: []
+}) as angular.IDirectiveFactory);
+
 directiveModule.directive('ng2MultilineEllipsis', downgradeComponent({
   component: MultilineEllipsisComponent,
   inputs: ['lines', 'lineHeight', 'className'],
@@ -309,6 +316,7 @@
   inputs: [],
   outputs: []
 }) as angular.IDirectiveFactory);
+
 directiveModule.directive('deploymentArtifactPage', downgradeComponent({
   component: DeploymentArtifactsPageComponent,
   inputs: [],
diff --git a/catalog-ui/src/app/modules/view-model-module.ts b/catalog-ui/src/app/modules/view-model-module.ts
index 5b8fc59..dd08135 100644
--- a/catalog-ui/src/app/modules/view-model-module.ts
+++ b/catalog-ui/src/app/modules/view-model-module.ts
@@ -36,6 +36,7 @@
 import {ManagementWorkflowViewModel} from "../view-models/workspace/tabs/management-workflow/management-workflow-view-model";
 import {InterfaceOperationViewModel} from "../view-models/workspace/tabs/interface-operation/interface-operation-view-model";
 import {NetworkCallFlowViewModel} from "../view-models/workspace/tabs/network-call-flow/network-call-flow-view-model";
+import {InterfaceDefinitionViewModel} from "../view-models/workspace/tabs/interface-definition/interface-definition-view-model";
 let moduleName:string = 'Sdc.ViewModels';
 let viewModelModule:ng.IModule = angular.module(moduleName, []);
 
@@ -59,4 +60,5 @@
   .controller(moduleName + '.PropertiesViewModel', PropertiesViewModel)
   .controller(moduleName + '.ManagementWorkflowViewModel', ManagementWorkflowViewModel)
   .controller(moduleName + '.InterfaceOperationViewModel', InterfaceOperationViewModel)
+  .controller(moduleName + '.InterfaceDefinitionViewModel', InterfaceDefinitionViewModel)
   .controller(moduleName + '.NetworkCallFlowViewModel', NetworkCallFlowViewModel);
diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts
index 5b12ae9..f6ba919 100644
--- a/catalog-ui/src/app/ng2/app.module.ts
+++ b/catalog-ui/src/app/ng2/app.module.ts
@@ -102,6 +102,7 @@
 import { ElementService } from "./services/element.service";
 import { ModelService } from "./services/model.service";
 import {ToscaArtifactService} from "./services/tosca-artifact.service";
+import {InterfaceDefinitionModule} from "./pages/interface-definition/interface-definition.module";
 
 
 declare const __ENV__: string;
@@ -156,8 +157,9 @@
     PluginFrameModule,
     PluginsModule,
     InterfaceOperationModule,
+    InterfaceDefinitionModule,
     OperationCreatorModule,
-        InterfaceOperationHandlerModule,
+    InterfaceOperationHandlerModule,
     ServicePathCreatorModule,
     ServicePathsListModule,
     ServicePathSelectorModule,
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 2cc91a9..60d6678 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
@@ -227,7 +227,8 @@
           toscaArtifactTypes: this.toscaArtifactTypes,
           selectedInterface: interfaceModel,
           selectedInterfaceOperation: operation,
-          validityChangedCallback: this.enableOrDisableSaveButton
+          validityChangedCallback: this.enableOrDisableSaveButton,
+          isViewOnly: false
         }
     );
     this.modalInstance.instance.open();
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 428c4cd..6dec416 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
@@ -28,7 +28,7 @@
                 <sdc-input
                     label="{{ 'OPERATION_INTERFACE_TYPE' | translate }}"
                     [(value)]="interfaceType"
-                    [disabled]="true">
+                    [disabled]=isViewOnly>
                 </sdc-input>
             </div>
 
@@ -36,7 +36,7 @@
                 <sdc-input
                     label="{{ 'OPERATION_NAME' | translate }}"
                     [(value)]="operationToUpdate.name"
-                    [disabled]="true">
+                    [disabled]=isViewOnly>
                 </sdc-input>
             </div>
         </div>
@@ -46,7 +46,8 @@
                 label="{{'OPERATION_DESCRIPTION' | translate}}"
                 [(value)]="operationToUpdate.description"
                 testId="interface-operation-description"
-                (valueChange)="onDescriptionChange($event)">
+                (valueChange)="onDescriptionChange($event)"
+                [disabled]=isViewOnly>
             </sdc-input>
         </div>
 
@@ -55,7 +56,8 @@
             <div class="form-item">
                 <checkbox [label]="'Add Artifact To Implementation'"
                           [(checked)]="enableAddArtifactImplementation"
-                          (checkedChange)="onMarkToAddArtifactToImplementation($event)">
+                          (checkedChange)="onMarkToAddArtifactToImplementation($event)"
+                          [disabled]=isViewOnly>
                 </checkbox>
             </div>
             <div class="form-item" *ngIf="!enableAddArtifactImplementation">
@@ -63,7 +65,8 @@
                     label="{{'INTERFACE_OPERATION_IMPLEMENTATION_NAME' | translate}}"
                     testId="interface-operation-implementation-name"
                     [(value)]="artifactName"
-                    (valueChange)="onImplementationNameChange($event)">
+                    (valueChange)="onImplementationNameChange($event)"
+                    [disabled]=isViewOnly>
                 </sdc-input>
             </div>
 
@@ -76,7 +79,8 @@
                         [selectedOption]="toscaArtifactTypeSelected"
                         placeHolder="{{toscaArtifactTypeSelected != undefined ? toscaArtifactTypeSelected : 'Select...'}}"
                         (changed)="onSelectToscaArtifactType($event)"
-                        [options]="toscaArtifactTypes">
+                        [options]="toscaArtifactTypes"
+                        [disabled]=isViewOnly>
                     </sdc-dropdown>
                 </div>
                 <div class="form-item" *ngIf="toscaArtifactTypeSelected && enableAddArtifactImplementation">
@@ -85,7 +89,8 @@
                         data-tests-id="artifactFile"
                         [(value)]="artifactName"
                         [required]="true"
-                        (valueChange)="onArtifactFileChange($event)">
+                        (valueChange)="onArtifactFileChange($event)"
+                        [disabled]=isViewOnly>
                     </sdc-input>
                 </div>
                 <div class="form-item">
@@ -93,7 +98,8 @@
                         label="{{ 'ARTIFACT_VERSION' | translate }}"
                         data-tests-id="artifactVersion"
                         [(value)]="artifactVersion"
-                        (valueChange)="onArtifactVersionChange($event)">
+                        (valueChange)="onArtifactVersionChange($event)"
+                        [disabled]=isViewOnly>
                     </sdc-input>
                 </div>
             </div>
@@ -122,7 +128,7 @@
         <div class="separator-buttons">
             <tab tabTitle="Inputs"></tab>
             <a class="add-param-link add-btn"
-               [ngClass]="{'disabled': readonly}"
+               [ngClass]="{'disabled': readonly || isViewOnly}"
                (click)="onAddInput()">{{'OPERATION_ADD_INPUT' | translate}}
             </a>
         </div>
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 6e4ae45..1099391 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
@@ -49,6 +49,7 @@
         selectedInterface: UIInterfaceModel;
         selectedInterfaceOperation: InterfaceOperationModel;
         validityChangedCallback: Function;
+        isViewOnly: boolean;
     };
 
     interfaceType: string;
@@ -60,6 +61,7 @@
     properties: Array<PropertyParamRowComponent> = [];
     isLoading: boolean = false;
     readonly: boolean;
+    isViewOnly: boolean;
 
     toscaArtifactTypeSelected: string;
     toscaArtifactTypeProperties: Array<PropertyBEModel> = [];
@@ -70,6 +72,7 @@
     propertyValueValid: boolean = true;
 
     ngOnInit() {
+        this.isViewOnly = this.input.isViewOnly;
         this.interfaceType = this.input.selectedInterface.displayType();
         this.operationToUpdate = new InterfaceOperationModel(this.input.selectedInterfaceOperation);
         this.operationToUpdate.interfaceId = this.input.selectedInterface.uniqueId;
diff --git a/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.module.ts b/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.module.ts
new file mode 100644
index 0000000..27a7f11
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.module.ts
@@ -0,0 +1,47 @@
+/*
+* ============LICENSE_START=======================================================
+* SDC
+* ================================================================================
+*  Copyright (C) 2022 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 {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
+import {TranslateModule} from "app/ng2/shared/translator/translate.module";
+import { SdcUiComponentsModule } from 'onap-ui-angular';
+import {InterfaceDefinitionComponent} from "./interface-definition.page.component";
+import {InterfaceOperationHandlerModule} from "../composition/interface-operatons/operation-creator/interface-operation-handler.module";
+
+@NgModule({
+    declarations: [
+        InterfaceDefinitionComponent,
+    ],
+    imports: [
+        CommonModule,
+        SdcUiComponentsModule,
+        UiElementsModule,
+        TranslateModule,
+        InterfaceOperationHandlerModule
+    ],
+    exports: [],
+    entryComponents: [
+        InterfaceDefinitionComponent
+    ],
+    providers: []
+})
+
+export class InterfaceDefinitionModule {}
diff --git a/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.html b/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.html
new file mode 100644
index 0000000..25ccf11
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.html
@@ -0,0 +1,85 @@
+<!--
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 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-definition">
+  <loader [display]="isLoading" [size]="'large'" [relative]="true"></loader>
+  <div *ngIf="isInterfaceListEmpty()">
+    <div class="interface-empty-msg">
+      <div>{{ 'INTERFACE_DATA_EMPTY' | translate }}</div>
+    </div>
+  </div>
+  <div class="operation-list">
+    <div *ngIf="!isInterfaceListEmpty()">
+      <div class="expand-collapse" *ngIf="isOperationListEmpty()">
+        <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 interface of interfaces">
+        <div class="interface-accordion" (click)="interface.toggleCollapse()">
+          <span
+              class="chevron-container"
+              [ngClass]="{'isCollapsed': interface.isCollapsed}"
+              *ngIf="isOperationListEmpty()">
+              <svg-icon
+                  name="caret1-down-o"
+                  mode="primary"
+                  size="small">
+              </svg-icon>
+          </span>
+          <span class="interface-name">{{interface.type}}</span>
+        </div>
+
+        <div class="generic-table" *ngIf="!interface.isCollapsed && isOperationListEmpty()">
+          <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 interface.operations"
+               (click)="onSelectInterfaceOperation(interface, 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/interface-definition/interface-definition.page.component.less b/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.less
new file mode 100644
index 0000000..2b76c8c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.less
@@ -0,0 +1,234 @@
+/*
+* ============LICENSE_START=======================================================
+* SDC
+* ================================================================================
+*  Copyright (C) 2022 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 '../../../../assets/styles/variables.less';
+@import '../../../../assets/styles/override.less';
+
+.interface-definition {
+    font-size: 14px;
+
+    .interface-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;
+    }
+
+    .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/interface-definition/interface-definition.page.component.ts b/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.ts
new file mode 100644
index 0000000..2a77b5e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.ts
@@ -0,0 +1,233 @@
+/*
+* ============LICENSE_START=======================================================
+* SDC
+* ================================================================================
+*  Copyright (C) 2022 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, Inject, ComponentRef} from '@angular/core';
+import {Component as IComponent } from 'app/models/components/component';
+
+import { SdcConfigToken, ISdcConfig } from "app/ng2/config/sdc-config.config";
+import {TranslateService } from "app/ng2/shared/translator/translate.service";
+
+import { ModalComponent } from 'app/ng2/components/ui/modal/modal.component';
+import {ModalService } from 'app/ng2/services/modal.service';
+import {
+    OperationModel,
+    InterfaceModel,
+    CapabilitiesGroup,
+    ButtonModel, ModalModel
+} from 'app/models';
+
+import {ComponentServiceNg2 } from 'app/ng2/services/component-services/component.service';
+
+import { SdcUiServices } from 'onap-ui-angular';
+import {TopologyTemplateService} from "../../services/component-services/topology-template.service";
+import {InputOperationParameter, InterfaceOperationModel} from "../../../models/interfaceOperation";
+import {PropertyParamRowComponent} from "../composition/interface-operatons/operation-creator/property-param-row/property-param-row.component";
+import {InterfaceOperationHandlerComponent} from "../composition/interface-operatons/operation-creator/interface-operation-handler.component";
+import {DropdownValue} from "../../components/ui/form-components/dropdown/ui-element-dropdown.component";
+
+export class UIOperationModel extends OperationModel {
+    isCollapsed: boolean = true;
+    isEllipsis: boolean;
+    MAX_LENGTH = 75;
+
+    constructor(operation: OperationModel) {
+        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;
+    }
+}
+
+// tslint:disable-next-line:max-classes-per-file
+class ModalTranslation {
+    CREATE_TITLE: string;
+    EDIT_TITLE: string;
+    DELETE_TITLE: string;
+    CANCEL_BUTTON: string;
+    SAVE_BUTTON: string;
+    CREATE_BUTTON: string;
+    DELETE_BUTTON: string;
+    deleteText: Function;
+
+    constructor(private TranslateService: TranslateService) {
+        this.TranslateService.languageChangedObservable.subscribe(lang => {
+            this.CREATE_TITLE = this.TranslateService.translate("INTERFACE_CREATE_TITLE");
+            this.EDIT_TITLE = this.TranslateService.translate('INTERFACE_EDIT_TITLE');
+            this.DELETE_TITLE = this.TranslateService.translate("INTERFACE_DELETE_TITLE");
+            this.CANCEL_BUTTON = this.TranslateService.translate("INTERFACE_CANCEL_BUTTON");
+            this.SAVE_BUTTON = this.TranslateService.translate("INTERFACE_SAVE_BUTTON");
+            this.CREATE_BUTTON = this.TranslateService.translate("INTERFACE_CREATE_BUTTON");
+            this.DELETE_BUTTON = this.TranslateService.translate("INTERFACE_DELETE_BUTTON");
+            this.deleteText = (operationName) => this.TranslateService.translate("INTERFACE_DELETE_TEXT", {operationName});
+        });
+    }
+}
+
+// tslint:disable-next-line:max-classes-per-file
+export class UIInterfaceModel extends InterfaceModel {
+    isCollapsed: boolean = false;
+
+    constructor(interfaceData?: any) {
+        super(interfaceData);
+        this.operations = _.map(
+            this.operations,
+            (operation) => new UIOperationModel(operation)
+        );
+    }
+
+    toggleCollapse() {
+        this.isCollapsed = !this.isCollapsed;
+    }
+}
+
+// tslint:disable-next-line:max-classes-per-file
+@Component({
+    selector: 'interface-definition',
+    templateUrl: './interface-definition.page.component.html',
+    styleUrls: ['interface-definition.page.component.less'],
+    providers: [ModalService, TranslateService]
+})
+
+export class InterfaceDefinitionComponent {
+
+    modalInstance: ComponentRef<ModalComponent>;
+    interfaces: UIInterfaceModel[];
+    inputs: Array<InputOperationParameter> = [];
+
+    properties: Array<PropertyParamRowComponent> = [];
+    deploymentArtifactsFilePath: Array<DropdownValue> = [];
+
+    toscaArtifactTypes: Array<DropdownValue> = [];
+
+    isLoading: boolean;
+    interfaceTypes: { [interfaceType: string]: string[] };
+    modalTranslation: ModalTranslation;
+    workflows: any[];
+    capabilities: CapabilitiesGroup;
+
+    @Input() component: IComponent;
+    @Input() readonly: boolean;
+    @Input() enableMenuItems: Function;
+    @Input() disableMenuItems: Function;
+
+    constructor(
+        @Inject(SdcConfigToken) private sdcConfig: ISdcConfig,
+        @Inject("$state") private $state: ng.ui.IStateService,
+        private translateService: TranslateService,
+        private componentServiceNg2: ComponentServiceNg2,
+        private modalServiceNg2: ModalService,
+        private modalServiceSdcUI: SdcUiServices.ModalService,
+        private topologyTemplateService: TopologyTemplateService
+    ) {
+        this.modalTranslation = new ModalTranslation(translateService);
+    }
+
+    ngOnInit(): void {
+        if(this.component) {
+            this.initInterfaceDefinition();
+        }
+    }
+
+    private cancelAndCloseModal = () => {
+        return this.modalServiceNg2.closeCurrentModal();
+    }
+
+    private enableOrDisableSaveButton = (): boolean => {
+        return true;
+    }
+
+    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', () =>
+        null, this.enableOrDisableSaveButton);
+        const interfaceDataModal: ModalModel =
+            new ModalModel('l', this.modalTranslation.EDIT_TITLE, '', [saveButton, cancelButton], 'custom');
+        this.modalInstance = this.modalServiceNg2.createCustomModal(interfaceDataModal);
+
+        this.modalServiceNg2.addDynamicContentToModal(
+            this.modalInstance,
+            InterfaceOperationHandlerComponent,
+            {
+                deploymentArtifactsFilePath: this.deploymentArtifactsFilePath,
+                toscaArtifactTypes: this.toscaArtifactTypes,
+                selectedInterface: interfaceModel,
+                selectedInterfaceOperation: operation,
+                validityChangedCallback: this.enableOrDisableSaveButton,
+                isViewOnly: true
+            }
+        );
+        this.modalInstance.instance.open();
+    }
+
+    private initInterfaceDefinition() {
+        this.isLoading = true;
+        this.interfaces = [];
+        this.topologyTemplateService.getComponentInterfaceOperations(this.component.componentType, this.component.uniqueId)
+        .subscribe((response) => {
+            if (response.interfaces) {
+                this.interfaces = _.map(response.interfaces, (interfaceModel) => new UIInterfaceModel(interfaceModel));
+            }
+            this.isLoading = false;
+        });
+    }
+
+    collapseAll(value: boolean = true): void {
+        _.forEach(this.interfaces, (interfaceData) => {
+            interfaceData.isCollapsed = value;
+        });
+    }
+
+    isAllCollapsed(): boolean {
+        return _.every(this.interfaces, (interfaceData) => interfaceData.isCollapsed);
+    }
+
+    isAllExpanded(): boolean {
+        return _.every(this.interfaces, (interfaceData) => !interfaceData.isCollapsed);
+    }
+
+    isInterfaceListEmpty(): boolean {
+        return this.interfaces.length === 0;
+    }
+
+    isOperationListEmpty(): boolean {
+        return _.filter(this.interfaces, (interfaceData) =>
+            interfaceData.operations && interfaceData.operations.length > 0).length > 0;
+    }
+
+}
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 20425f8..49f273c 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
@@ -145,6 +145,10 @@
         return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INFORMATIONAL_ARTIFACTS]);
     }
 
+    getComponentInterfaceOperations(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+        return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_INTERFACE_OPERATIONS]);
+    }
+
     getComponentInformationalArtifactsAndInstances(component: Component): Observable<ComponentGenericResponse> {
         return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INFORMATIONAL_ARTIFACTS, COMPONENT_FIELDS.COMPONENT_INSTANCES]);
     }
diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts
index 58aa402..ab706e7 100644
--- a/catalog-ui/src/app/utils/constants.ts
+++ b/catalog-ui/src/app/utils/constants.ts
@@ -292,6 +292,7 @@
   public static WORKSPACE_TOSCA_ARTIFACTS = 'workspace.tosca_artifacts';
   public static WORKSPACE_COMPOSITION = 'workspace.composition';
   public static WORKSPACE_INTERFACE_OPERATION = 'workspace.interface_operation';
+  public static WORKSPACE_INTERFACE_DEFINITION = 'workspace.interface-definition';
   public static WORKSPACE_NETWORK_CALL_FLOW = 'workspace.network_call_flow';
   public static WORKSPACE_MANAGEMENT_WORKFLOW = 'workspace.management_workflow';
   public static WORKSPACE_DEPLOYMENT = 'workspace.deployment';
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/interface-definition/interface-definition-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/interface-definition/interface-definition-view-model.ts
new file mode 100644
index 0000000..46ba031
--- /dev/null
+++ b/catalog-ui/src/app/view-models/workspace/tabs/interface-definition/interface-definition-view-model.ts
@@ -0,0 +1,35 @@
+/*
+* ============LICENSE_START=======================================================
+* SDC
+* ================================================================================
+*  Copyright (C) 2022 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=========================================================
+*/
+'use strict';
+
+import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model";
+
+export interface IInterfaceDefinitionViewModelScope extends IWorkspaceViewModelScope {};
+
+export class InterfaceDefinitionViewModel {
+
+    static '$inject' = [
+        '$scope'
+    ];
+
+    constructor(private $scope: IInterfaceDefinitionViewModelScope) {}
+
+}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/interface-definition/interface-definition-view.html b/catalog-ui/src/app/view-models/workspace/tabs/interface-definition/interface-definition-view.html
new file mode 100644
index 0000000..4eba488
--- /dev/null
+++ b/catalog-ui/src/app/view-models/workspace/tabs/interface-definition/interface-definition-view.html
@@ -0,0 +1,27 @@
+<!--
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 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="workspace-interface-definition">
+    <interface-definition
+        [component]="component"
+        [readonly]="isViewMode() || !isDesigner()"
+        [disableMenuItems]="disableMenuItems"
+        [enableMenuItems]="enableMenuItems">
+    </interface-definition>
+</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/interface-definition/interface-definition.less b/catalog-ui/src/app/view-models/workspace/tabs/interface-definition/interface-definition.less
new file mode 100644
index 0000000..ce0264e
--- /dev/null
+++ b/catalog-ui/src/app/view-models/workspace/tabs/interface-definition/interface-definition.less
@@ -0,0 +1,26 @@
+/*
+* ============LICENSE_START=======================================================
+* SDC
+* ================================================================================
+*  Copyright (C) 2022 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=========================================================
+*/
+.workspace-interface-definition {
+    width: 100%;
+    display: inline-block;
+    top: -26px;
+    position: relative;
+}