aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app
diff options
context:
space:
mode:
authorArielk <Ariel.Kenan@amdocs.com>2018-04-16 15:37:39 +0300
committerAvi Gaffa <avi.gaffa@amdocs.com>2018-05-01 03:38:57 +0000
commit802bd2af2e3c6ba92eb1ce0180a13b11018f6695 (patch)
tree0906a846aa2c3edc9f2067364ed812bdead9f939 /catalog-ui/src/app
parentd0f6cb3ef9600846358a0e7f849759be6f9d917e (diff)
Interface Operation tab and screens
Change-Id: If03234c783d6ce16fdd0945987ada83b6285f97f Issue-ID: SDC-1060 Signed-off-by: Arielk <Ariel.Kenan@amdocs.com>
Diffstat (limited to 'catalog-ui/src/app')
-rw-r--r--catalog-ui/src/app/app.ts13
-rw-r--r--catalog-ui/src/app/models.ts1
-rw-r--r--catalog-ui/src/app/models/components/component.ts4
-rw-r--r--catalog-ui/src/app/models/operation.ts51
-rw-r--r--catalog-ui/src/app/modules/directive-module.ts9
-rw-r--r--catalog-ui/src/app/modules/view-model-module.ts2
-rw-r--r--catalog-ui/src/app/ng2/app.module.ts4
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.module.ts19
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html38
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.less88
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts176
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html59
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less69
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts68
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.module.ts27
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html21
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less29
-rw-r--r--catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts15
-rw-r--r--catalog-ui/src/app/ng2/services/component-services/component.service.ts44
-rw-r--r--catalog-ui/src/app/ng2/services/responses/component-generic-response.ts6
-rw-r--r--catalog-ui/src/app/utils/common-utils.ts34
-rw-r--r--catalog-ui/src/app/utils/constants.ts3
-rw-r--r--catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view-model.ts15
-rw-r--r--catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view.html3
-rw-r--r--catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation.less6
-rw-r--r--catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view-model.ts6
26 files changed, 803 insertions, 7 deletions
diff --git a/catalog-ui/src/app/app.ts b/catalog-ui/src/app/app.ts
index 48f15c057d..a9ec17cc14 100644
--- a/catalog-ui/src/app/app.ts
+++ b/catalog-ui/src/app/app.ts
@@ -508,9 +508,22 @@ ng1appModule.config([
);
$stateProvider.state(
+ States.WORKSPACE_INTERFACE_OPERATION, {
+ url: 'interface_operation',
+ parent: 'workspace',
+ controller: viewModelsModuleName + '.InterfaceOperationViewModel',
+ templateUrl: './view-models/workspace/tabs/interface-operation/interface-operation-view.html',
+ data: {
+ bodyClass: 'interface_operation'
+ }
+ }
+ );
+
+ $stateProvider.state(
'workspace.plugins', {
url: 'plugins/*path',
parent: 'workspace',
+ params: {'queryParams': null},
templateUrl: './view-models/workspace/tabs/plugins/plugins-context-view.html',
controller: viewModelsModuleName + '.PluginsContextViewModel'
}
diff --git a/catalog-ui/src/app/models.ts b/catalog-ui/src/app/models.ts
index ac26302c1f..3a48335c22 100644
--- a/catalog-ui/src/app/models.ts
+++ b/catalog-ui/src/app/models.ts
@@ -97,6 +97,7 @@ export * from './models/instance-inputs-properties-map';
export * from './models/left-panel';
export * from './models/member';
export * from './models/modules/base-module';
+export * from './models/operation';
export * from './models/properties';
export * from './models/requirement';
export * from './models/server-error-response';
diff --git a/catalog-ui/src/app/models/components/component.ts b/catalog-ui/src/app/models/components/component.ts
index b7f57227ca..adcf498342 100644
--- a/catalog-ui/src/app/models/components/component.ts
+++ b/catalog-ui/src/app/models/components/component.ts
@@ -23,7 +23,7 @@
import * as _ from "lodash";
import {AsdcComment, ArtifactModel, ArtifactGroupModel, IFileDownload, PropertyModel, PropertiesGroup, AttributeModel, AttributesGroup, ComponentInstance,
InputModel, DisplayModule, Module, IValidate, RelationshipModel, IMainCategory, RequirementsGroup, CapabilitiesGroup, AdditionalInformationModel,
- Resource, IAppMenu, Service} from "../../models";
+ Resource, IAppMenu, OperationModel, Service} from "../../models";
import {IComponentService} from "../../services/components/component-service";
import {CommonUtils} from "../../utils/common-utils";
@@ -134,6 +134,7 @@ export abstract class Component implements IComponent {
public deploymentArtifacts:ArtifactGroupModel;
public artifacts:ArtifactGroupModel;
public toscaArtifacts:ArtifactGroupModel;
+ public interfaceOperations:Array<OperationModel>;
public distributionStatus:string;
public categories:Array<IMainCategory>;
public categoryNormalizedName: string;
@@ -178,6 +179,7 @@ export abstract class Component implements IComponent {
this.additionalInformation = component.additionalInformation;
this.artifacts = new ArtifactGroupModel(component.artifacts);
this.toscaArtifacts = new ArtifactGroupModel(component.toscaArtifacts);
+ this.interfaceOperations = component.interfaceOperations;
this.contactId = component.contactId;
this.categories = component.categories;
this.categoryNormalizedName = component.categoryNormalizedName;
diff --git a/catalog-ui/src/app/models/operation.ts b/catalog-ui/src/app/models/operation.ts
new file mode 100644
index 0000000000..55fcd82320
--- /dev/null
+++ b/catalog-ui/src/app/models/operation.ts
@@ -0,0 +1,51 @@
+'use strict';
+
+export class OperationParam {
+ paramName: string = '';
+ paramId: string = '';
+
+ constructor(param?: OperationParam) {
+ if (param) {
+ this.paramId = param.paramId;
+ this.paramName = param.paramName;
+ }
+ }
+}
+
+export interface IOperationParamsList {
+ listToscaDataDefinition: Array<OperationParam>;
+}
+
+export class OperationModel {
+ description: string;
+ inputParams: IOperationParamsList;
+ operationType: string;
+ outputParams: IOperationParamsList;
+ uniqueId: string;
+
+ constructor(operation?: any) {
+ if (operation) {
+ this.description = operation.description;
+ this.inputParams = operation.inputParams;
+ this.operationType = operation.operationType;
+ this.outputParams = operation.outputParams;
+ this.uniqueId = operation.uniqueId;
+ }
+ }
+
+ public createInputParamsList(inputParams: Array<OperationParam>): void {
+ this.inputParams = {
+ listToscaDataDefinition: inputParams
+ };
+ }
+
+ public createOutputParamsList(outputParams: Array<OperationParam>): void {
+ this.outputParams = {
+ listToscaDataDefinition: outputParams
+ };
+ }
+}
+
+export interface CreateOperationResponse extends OperationModel {
+ artifactUUID: string;
+}
diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts
index 6285415056..d409da0c4d 100644
--- a/catalog-ui/src/app/modules/directive-module.ts
+++ b/catalog-ui/src/app/modules/directive-module.ts
@@ -183,7 +183,8 @@ import { SearchWithAutoCompleteComponent } from "../ng2/components/ui/search-wit
import { PalettePopupPanelComponent } from "../ng2/components/ui/palette-popup-panel/palette-popup-panel.component";
import { ServicePathComponent } from '../ng2/components/logic/service-path/service-path.component';
import { ServicePathSelectorComponent } from '../ng2/components/logic/service-path-selector/service-path-selector.component';
-import {PluginFrameComponent} from "../ng2/components/ui/plugin/plugin-frame.component";
+import { InterfaceOperationComponent } from '../ng2/pages/interface-operation/interface-operation.page.component';
+import { PluginFrameComponent } from "../ng2/components/ui/plugin/plugin-frame.component";
directiveModule.directive('menuListNg2', downgradeComponent({
component: MenuListNg2Component,
@@ -242,6 +243,12 @@ directiveModule.directive('ng2ServicePathSelector', downgradeComponent({
outputs: []
}) as angular.IDirectiveFactory);
+directiveModule.directive('ng2InterfaceOperation', downgradeComponent({
+ component: InterfaceOperationComponent,
+ inputs: ['component', 'readonly', 'state'],
+ outputs: []
+}) as angular.IDirectiveFactory);
+
directiveModule.directive('pluginFrame', downgradeComponent( {
component: PluginFrameComponent,
inputs: ['plugin', 'queryParams'],
diff --git a/catalog-ui/src/app/modules/view-model-module.ts b/catalog-ui/src/app/modules/view-model-module.ts
index a4f47ff9fc..de7d6d8a5d 100644
--- a/catalog-ui/src/app/modules/view-model-module.ts
+++ b/catalog-ui/src/app/modules/view-model-module.ts
@@ -64,6 +64,7 @@ import {PropertiesViewModel} from "../view-models/workspace/tabs/properties/prop
import {AttributesViewModel} from "../view-models/workspace/tabs/attributes/attributes-view-model";
import {ActivityLogViewModel} from "../view-models/workspace/tabs/activity-log/activity-log";
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 {DeploymentViewModel} from "../view-models/workspace/tabs/deployment/deployment-view-model";
import {ResourceInputsViewModel} from "../view-models/workspace/tabs/inputs/resource-input/resource-inputs-view-model";
@@ -131,6 +132,7 @@ viewModelModule
.controller(moduleName + '.AttributesViewModel', AttributesViewModel)
.controller(moduleName + '.ActivityLogViewModel', ActivityLogViewModel)
.controller(moduleName + '.ManagementWorkflowViewModel', ManagementWorkflowViewModel)
+ .controller(moduleName + '.InterfaceOperationViewModel', InterfaceOperationViewModel)
.controller(moduleName + '.NetworkCallFlowViewModel', NetworkCallFlowViewModel)
.controller(moduleName + '.DeploymentViewModel', DeploymentViewModel)
.controller(moduleName + '.ResourceInputsViewModel', ResourceInputsViewModel)
diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts
index 727f0fe8f5..194d2e0095 100644
--- a/catalog-ui/src/app/ng2/app.module.ts
+++ b/catalog-ui/src/app/ng2/app.module.ts
@@ -43,6 +43,8 @@ import {ComponentInstanceServiceNg2} from "./services/component-instance-service
import {ModalService} from "./services/modal.service";
import {UiElementsModule} from "./components/ui/ui-elements.module";
import {ConnectionWizardModule} from "./pages/connection-wizard/connection-wizard.module";
+import {InterfaceOperationModule} from "./pages/interface-operation/interface-operation.module";
+import {OperationCreatorModule} from "./pages/interface-operation/operation-creator/operation-creator.module";
import {LayoutModule} from "./components/layout/layout.module";
import {UserService} from "./services/user.service";
import {PoliciesService} from "./services/policies.service";
@@ -85,6 +87,8 @@ export function configServiceFactory(config:ConfigService) {
ConnectionWizardModule,
PropertiesAssignmentModule,
PluginFrameModule,
+ InterfaceOperationModule,
+ OperationCreatorModule,
ServicePathCreatorModule,
ServicePathsListModule,
ServicePathModule,
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.module.ts b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.module.ts
new file mode 100644
index 0000000000..caf6a3f528
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.module.ts
@@ -0,0 +1,19 @@
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {InterfaceOperationComponent} from "./interface-operation.page.component";
+
+@NgModule({
+ declarations: [
+ InterfaceOperationComponent
+ ],
+ imports: [
+ CommonModule
+ ],
+ exports: [],
+ entryComponents: [
+ InterfaceOperationComponent
+ ],
+ providers: []
+})
+
+export class InterfaceOperationModule {}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html
new file mode 100644
index 0000000000..25e8672db8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.html
@@ -0,0 +1,38 @@
+<div class="interface-operation">
+ <div
+ class="add-btn"
+ [ngClass]="{'disabled': readonly}"
+ data-tests-id="addInterfaceOperation"
+ (click)="onAddOperation()">
+ Add Operation
+ </div>
+
+ <div class="operation-list" [ngClass]="{'disabled': readonly}">
+
+ <div
+ class="operation-row"
+ *ngFor="let operation of operationList"
+ (click)="onEditOperation(operation)">
+
+ <span class="operation-info-container">
+ <span class="operation-title">
+ <p class="operation-text" data-tests-id="interfaceOperationType">{{operation.operationType}}</p>
+ </span>
+
+ <span class="operation-description">
+ <p class="operation-text" data-tests-id="interfaceOperationDescription">{{operation.description}}</p>
+ </span>
+ </span>
+
+ <span class="operation-dumbo">
+ <span
+ class="sprite-new delete-item-icon"
+ data-tests-id="deleteInterfaceOperation"
+ (click)="onRemoveOperation($event, operation)">
+ </span>
+ </span>
+
+ </div>
+ </div>
+
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.less b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.less
new file mode 100644
index 0000000000..435502066e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.less
@@ -0,0 +1,88 @@
+@import '../../../../assets/styles/variables.less';
+
+.interface-operation {
+ .add-btn {
+ position: relative;
+ top: -31px;
+ text-transform: uppercase;
+ font-size: 14px;
+ }
+
+ a:not(.disabled) {
+ &:hover {
+ cursor: pointer;
+ }
+ }
+
+ .operation-list {
+ border-top: 1px solid @main_color_o;
+ padding-top: 25px;
+
+ .operation-row {
+ width: 100%;
+ border: 1px solid @main_color_o;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ height: 100px;
+
+ &:hover {
+ border-color: @main_color_c;
+ cursor: pointer;
+ }
+
+ &:not(:first-child) {
+ margin-top: 20px;
+ }
+
+ .operation-info-container {
+ height: 100%;
+ display: flex;
+ align-items: center;
+ margin-right: 60px;
+
+ .operation-title, .operation-description {
+ display: flex;
+ align-items: center;
+
+ .operation-text {
+ overflow: hidden;
+ margin-bottom: 0;
+ max-height: 5rem;
+ }
+ }
+
+ .operation-title {
+ flex-shrink: 0;
+ width: 200px;
+ height: calc(100% - 13px);
+ border-right: 1px solid @main_color_o;
+ margin: 4px 0;
+ padding: 0 30px;
+
+ .operation-text {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+ }
+
+ .operation-description {
+ padding-left: 30px;
+ text-align: left;
+ font-family: @font-opensans-regular;
+
+ .operation-text {
+ word-break: break-word;
+ }
+ }
+ }
+
+ .operation-dumbo {
+ padding-right: 20px;
+ display: flex;
+ flex-direction: column;
+ align-items: left;
+ }
+ }
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts
new file mode 100644
index 0000000000..c58e1de135
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts
@@ -0,0 +1,176 @@
+import * as _ from "lodash";
+import {Component, Input, ComponentRef, Inject} from '@angular/core';
+import {Component as IComponent} from 'app/models/components/component';
+import {ModalService} from 'app/ng2/services/modal.service';
+import {ModalModel, ButtonModel, InputModel, OperationModel, CreateOperationResponse} from 'app/models';
+import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component';
+import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service';
+import {ComponentGenericResponse} from 'app/ng2/services/responses/component-generic-response';
+import {OperationCreatorComponent} from './operation-creator/operation-creator.component';
+
+@Component({
+ selector: 'interface-operation',
+ templateUrl: './interface-operation.page.component.html',
+ styleUrls: ['interface-operation.page.component.less'],
+ providers: [ModalService]
+})
+
+export class InterfaceOperationComponent {
+
+ modalInstance: ComponentRef<ModalComponent>;
+ operationList: Array<OperationModel> = [];
+ openOperation: OperationModel;
+
+ @Input() component: IComponent;
+ @Input() readonly: boolean;
+
+ constructor(
+ @Inject('$state') private $state:ng.ui.IStateService,
+ private ComponentServiceNg2: ComponentServiceNg2,
+ private ModalServiceNg2: ModalService,
+ ) {}
+
+ ngOnInit(): void {
+ this.ComponentServiceNg2.getInterfaceOperations(this.component).subscribe((response: ComponentGenericResponse) => {
+ let {interfaceOperations} = response;
+ this.component.interfaceOperations = interfaceOperations;
+ this.operationList = _.toArray(interfaceOperations);
+ });
+ }
+
+ getDisabled = (): boolean => {
+ return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
+ }
+
+ onEditOperation = (operation: OperationModel): void => {
+ this.ComponentServiceNg2
+ .getInterfaceOperation(this.component, operation)
+ .subscribe(op => this.onAddOperation(op));
+ }
+
+ onAddOperation = (operation?: OperationModel): void => {
+ const modalMap = {
+ create: {
+ modalTitle: 'Create a New Operation',
+ saveBtnText: 'Create',
+ submitCallback: this.createOperation,
+ },
+ edit: {
+ modalTitle: 'Edit Operation',
+ saveBtnText: 'Save',
+ submitCallback: this.updateOperation,
+ }
+ };
+
+ const modalData = operation ? modalMap.edit : modalMap.create;
+
+ if (this.openOperation) {
+ if (operation ? operation.uniqueId === this.openOperation.uniqueId : !this.openOperation.uniqueId) {
+ operation = this.openOperation;
+ }
+ }
+
+ this.ComponentServiceNg2.getComponentInputs(this.component).subscribe((response: ComponentGenericResponse) => {
+
+ const cancelButton: ButtonModel = new ButtonModel(
+ 'Cancel',
+ 'outline white',
+ () => {
+ this.openOperation = null;
+ this.ModalServiceNg2.closeCurrentModal();
+ },
+ );
+
+ const saveButton: ButtonModel = new ButtonModel(
+ modalData.saveBtnText,
+ 'blue',
+ () => {
+ this.modalInstance.instance.dynamicContent.instance.createInputParamList();
+ this.ModalServiceNg2.closeCurrentModal();
+ const {operation} = this.modalInstance.instance.dynamicContent.instance;
+ this.openOperation = operation;
+ modalData.submitCallback(operation);
+ },
+ this.getDisabled,
+ );
+
+ const modalModel: ModalModel = new ModalModel(
+ 'l',
+ modalData.modalTitle,
+ '',
+ [saveButton, cancelButton],
+ 'standard',
+ );
+
+ this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel);
+ this.ModalServiceNg2.addDynamicContentToModal(
+ this.modalInstance,
+ OperationCreatorComponent,
+ {
+ operation,
+ inputProperties: response.inputs,
+ },
+ );
+
+ this.modalInstance.instance.open();
+ });
+ }
+
+ onRemoveOperation = (event: Event, operation: OperationModel): void => {
+ event.stopPropagation();
+
+ const confirmCallback = () => {
+ this.ModalServiceNg2.closeCurrentModal();
+ this.ComponentServiceNg2
+ .deleteInterfaceOperation(this.component, operation)
+ .subscribe(() => {
+ const index = _.findIndex(this.operationList, el => el.uniqueId === operation.uniqueId);
+ this.operationList.splice(index, 1);
+ this.component.interfaceOperations = this.operationList;
+ });
+ }
+
+ this.modalInstance = this.ModalServiceNg2.createActionModal(
+ operation.operationType,
+ 'Are you sure you want to delete this operation?',
+ 'Delete',
+ confirmCallback,
+ 'Cancel',
+ );
+
+ this.modalInstance.instance.open();
+ }
+
+ private createOperation = (operation: OperationModel): any => {
+ this.ComponentServiceNg2.createInterfaceOperation(this.component, operation).subscribe((response: CreateOperationResponse) => {
+ this.openOperation = null;
+
+ const workflowId = response.artifactUUID;
+ const operationId = response.uniqueId;
+ const resourceId = this.component.uuid;
+
+ const queryParams = {
+ id: workflowId,
+ operationID: operationId,
+ uuid: resourceId,
+ displayMode: 'create',
+ };
+
+ this.$state.go('workspace.plugins', {
+ path: 'workflowDesigner',
+ queryParams
+ });
+
+ });
+ }
+
+ private updateOperation = (operation: OperationModel): any => {
+ this.ComponentServiceNg2.updateInterfaceOperation(this.component, operation).subscribe(newOperation => {
+ this.openOperation = null;
+ const index = _.findIndex(this.operationList, el => el.uniqueId === operation.uniqueId);
+ this.operationList.splice(index, 1, newOperation);
+ this.component.interfaceOperations = this.operationList;
+ });
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html
new file mode 100644
index 0000000000..9e47cd5cef
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html
@@ -0,0 +1,59 @@
+<div class="operation-creator">
+ <form class="w-sdc-form">
+
+ <div class="side-by-side">
+ <div class="i-sdc-form-item">
+ <label class="i-sdc-form-label">Operation Type</label>
+ <input
+ type="text"
+ data-tests-id="operationType"
+ name="operationType"
+ [(ngModel)]="operation.operationType"
+ [attr.maxLength]="200"
+ [disabled]="isEditMode" />
+ </div>
+
+ <div class="i-sdc-form-item" >
+ <label class="i-sdc-form-label">Description</label>
+ <input
+ type="text"
+ data-tests-id="operationDescription"
+ name="description"
+ [(ngModel)]="operation.description"
+ [attr.maxLength]="200" />
+ </div>
+ </div>
+
+ <div class="separator-buttons">
+ <span class="input-param-title">Input Parameters</span>
+ <a
+ class="add-param-link"
+ data-tests-id="addInputParameter"
+ [ngClass]="{'disabled':!isAddAllowed()}"
+ (click)="addParam()">
+ Add Input Parameter
+ </a>
+ </div>
+
+ <div class="generic-table">
+ <div class="header-row table-row">
+ <span class="cell header-cell">Name</span>
+ <span class="cell header-cell">Property Name</span>
+ <span class="cell header-cell"></span>
+ </div>
+
+ <div class="empty-msg data-row" *ngIf="inputParams.length === 0">
+ No data to display.
+ </div>
+
+ <param-row
+ *ngFor="let param of inputParams; let idx=index"
+ class="data-row"
+ [param]="param"
+ [inputProps]="inputProperties"
+ [onRemoveParam]="onRemoveParam">
+ </param-row>
+ </div>
+
+ </form>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less
new file mode 100644
index 0000000000..289dd5b452
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.less
@@ -0,0 +1,69 @@
+@import '../../../../../assets/styles/variables.less';
+
+.operation-creator {
+ 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;
+ }
+
+ .side-by-side {
+ display: flex;
+
+ .i-sdc-form-item {
+ flex-basis: 100%;
+
+ &:first-child {
+ flex-basis: 40%;
+ margin-right: 10px;
+ }
+ }
+ }
+
+ .input-param-title {
+ font-size: 16px;
+ text-transform: uppercase;
+ }
+
+ .separator-buttons {
+ margin: 10px 0;
+ display: flex;
+ justify-content: space-between;
+
+ .add-param-link {
+ &:not(.disabled):hover {
+ cursor: pointer;
+ }
+ }
+ }
+
+ .generic-table {
+ max-height: 233px;
+
+ .header-row .header-cell {
+ &:last-child {
+ padding: 0;
+ }
+ }
+
+ .data-row {
+ &.empty-msg {
+ padding: 6px 14px;
+ }
+ }
+
+ /deep/ .cell {
+ &:last-child {
+ min-width: 40px;
+ }
+ }
+
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts
new file mode 100644
index 0000000000..cc7b5feaf3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts
@@ -0,0 +1,68 @@
+import * as _ from "lodash";
+import {Component} from '@angular/core';
+import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {InputModel, OperationModel, OperationParam} from 'app/models';
+
+@Component({
+ selector: 'operation-creator',
+ templateUrl: './operation-creator.component.html',
+ styleUrls:['./operation-creator.component.less'],
+})
+
+export class OperationCreatorComponent {
+
+ inputProperties: Array<DropdownValue>;
+ input: any;
+ inputParams: Array<OperationParam> = [];
+ operation: OperationModel;
+ isEditMode: boolean = false;
+
+ ngOnInit() {
+ this.operation = new OperationModel(this.input.operation || {});
+
+ if (this.input.operation) {
+ let {inputParams} = this.input.operation;
+
+ if (inputParams) {
+ _.forEach(inputParams.listToscaDataDefinition, (input: OperationParam) => {
+ this.addParam(input);
+ });
+ }
+
+ if (this.input.operation.uniqueId) {
+ this.isEditMode = true;
+ }
+ }
+
+ this.inputProperties = _.map(this.input.inputProperties,
+ (input: InputModel) => new DropdownValue(input.uniqueId, input.name)
+ );
+ }
+
+ addParam(param?: OperationParam): void {
+ this.inputParams.push(new OperationParam(param));
+ }
+
+ isAddAllowed(): boolean {
+ if (this.inputParams.length === 0) {
+ return true;
+ }
+
+ const {paramId, paramName} = _.last(this.inputParams);
+ return paramId && paramName.length > 0;
+ }
+
+ onRemoveParam = (param: OperationParam): void => {
+ let index = _.indexOf(this.inputParams, param);
+ this.inputParams.splice(index, 1);
+ }
+
+ createInputParamList(): void {
+ this.operation.createInputParamsList(this.inputParams);
+ }
+
+ checkFormValidForSubmit(): boolean {
+ return this.operation.operationType && this.operation.operationType.length > 0 && this.isAddAllowed();
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.module.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.module.ts
new file mode 100644
index 0000000000..9128e74641
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.module.ts
@@ -0,0 +1,27 @@
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {OperationCreatorComponent} from "./operation-creator.component";
+import {FormsModule} from "@angular/forms";
+import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
+import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
+import {ParamRowComponent} from './param-row/param-row.component';
+
+@NgModule({
+ declarations: [
+ OperationCreatorComponent,
+ ParamRowComponent
+ ],
+ imports: [
+ CommonModule,
+ FormsModule,
+ FormElementsModule,
+ UiElementsModule
+ ],
+ exports: [],
+ entryComponents: [
+ OperationCreatorComponent
+ ],
+ providers: []
+})
+
+export class OperationCreatorModule {}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html
new file mode 100644
index 0000000000..86d7628c17
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html
@@ -0,0 +1,21 @@
+<div class="cell">
+ <input
+ type="text"
+ data-tests-id="inputParamName"
+ [(ngModel)]="param.paramName" />
+</div>
+
+<ui-element-dropdown
+ class="cell"
+ data-tests-id="inputParamProperty"
+ [values]="inputProps"
+ [(value)]="param.paramId">
+</ui-element-dropdown>
+
+<div class="cell remove">
+ <span
+ class="sprite-new delete-item-icon"
+ data-tests-id="removeInputParam"
+ (click)="onRemoveParam(param)">
+ </span>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less
new file mode 100644
index 0000000000..9abd7c7681
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.less
@@ -0,0 +1,29 @@
+@import '../../../../../../assets/styles/variables.less';
+
+.remove {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .delete-item-icon {
+ &:hover {
+ cursor: pointer;
+ }
+ }
+}
+
+
+.cell {
+ padding: 0;
+
+ /deep/ select {
+ height: 30px;
+ border: none;
+ }
+
+ input {
+ height: 30px;
+ border: none;
+ padding-left: 10px;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts
new file mode 100644
index 0000000000..01e0629942
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.ts
@@ -0,0 +1,15 @@
+import {Component, Input} from '@angular/core';
+import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {OperationParam} from 'app/models';
+
+@Component({
+ selector: 'param-row',
+ templateUrl: './param-row.component.html',
+ styleUrls: ['./param-row.component.less']
+})
+
+export class ParamRowComponent {
+ @Input() param: OperationParam;
+ @Input() inputProps: Array<DropdownValue>;
+ @Input() onRemoveParam: Function;
+}
diff --git a/catalog-ui/src/app/ng2/services/component-services/component.service.ts b/catalog-ui/src/app/ng2/services/component-services/component.service.ts
index 9c3f78a444..381995d91c 100644
--- a/catalog-ui/src/app/ng2/services/component-services/component.service.ts
+++ b/catalog-ui/src/app/ng2/services/component-services/component.service.ts
@@ -24,7 +24,7 @@ import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import {Response, URLSearchParams} from '@angular/http';
-import { Component, InputBEModel, InstancePropertiesAPIMap, FilterPropertiesAssignmentData} from "app/models";
+import { Component, InputBEModel, InstancePropertiesAPIMap, FilterPropertiesAssignmentData, OperationModel, CreateOperationResponse} from "app/models";
import {COMPONENT_FIELDS} from "app/utils";
import {ComponentGenericResponse} from "../responses/component-generic-response";
import {InstanceBePropertiesMap} from "../../../models/properties-inputs/property-fe-map";
@@ -114,6 +114,48 @@ export class ComponentServiceNg2 {
return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_PROPERTIES]);
}
+ getInterfaceOperations(component:Component):Observable<ComponentGenericResponse> {
+ return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INTERFACE_OPERATIONS]);
+ }
+
+ getInterfaceOperation(component:Component, operation:OperationModel):Observable<OperationModel> {
+ return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaceOperations/' + operation.uniqueId)
+ .map((res:Response) => {
+ return res.json();
+ });
+ }
+
+ createInterfaceOperation(component:Component, operation:OperationModel):Observable<CreateOperationResponse> {
+ const operationList = {
+ 'interfaceOperations': {
+ [operation.operationType]: operation
+ }
+ };
+ return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaceOperations', operationList)
+ .map((res:Response) => {
+ return res.json();
+ });
+ }
+
+ updateInterfaceOperation(component:Component, operation:OperationModel):Observable<CreateOperationResponse> {
+ const operationList = {
+ 'interfaceOperations': {
+ [operation.operationType]: operation
+ }
+ };
+ return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaceOperations', operationList)
+ .map((res:Response) => {
+ return res.json();
+ });
+ }
+
+ deleteInterfaceOperation(component:Component, operation:OperationModel):Observable<OperationModel> {
+ return this.http.delete(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/interfaceOperations/' + operation.uniqueId)
+ .map((res:Response) => {
+ return res.json();
+ });
+ }
+
getCapabilitiesAndRequirements(componentType: string, componentId:string):Observable<ComponentGenericResponse> {
return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_REQUIREMENTS, COMPONENT_FIELDS.COMPONENT_CAPABILITIES]);
}
diff --git a/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts b/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts
index e7c88a0ab8..5036a10a9d 100644
--- a/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts
+++ b/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts
@@ -22,7 +22,7 @@
* Created by ob0695 on 4/18/2017.
*/
-import { ArtifactGroupModel, PropertyModel, PropertiesGroup, AttributeModel, AttributesGroup, ComponentInstance,
+import { ArtifactGroupModel, PropertyModel, PropertiesGroup, AttributeModel, AttributesGroup, ComponentInstance, OperationModel,
InputBEModel, Module, ComponentMetadata, RelationshipModel, RequirementsGroup, CapabilitiesGroup,InputFEModel} from "app/models";
import {CommonUtils} from "app/utils";
import {Serializable} from "../utils/serializable";
@@ -47,6 +47,7 @@ export class ComponentGenericResponse implements Serializable<ComponentGenericR
public policies:Array<PolicyInstance>;
public groups:Array<Module>;
public interfaces:any;
+ public interfaceOperations:Array<OperationModel>;
public additionalInformation:any;
public derivedList:Array<any>;
@@ -88,6 +89,9 @@ export class ComponentGenericResponse implements Serializable<ComponentGenericR
if(response.toscaArtifacts) {
this.toscaArtifacts = new ArtifactGroupModel(response.toscaArtifacts);
}
+ if(response.interfaces) {
+ this.interfaceOperations = CommonUtils.initInterfaceOperations(response.interfaces);
+ }
if(response.metadata) {
this.metadata = new ComponentMetadata().deserialize(response.metadata);
}
diff --git a/catalog-ui/src/app/utils/common-utils.ts b/catalog-ui/src/app/utils/common-utils.ts
index 97177949ee..1868550225 100644
--- a/catalog-ui/src/app/utils/common-utils.ts
+++ b/catalog-ui/src/app/utils/common-utils.ts
@@ -19,7 +19,7 @@
*/
import * as _ from "lodash";
-import {Module, AttributeModel, ResourceInstance, PropertyModel, InputFEModel} from "../models";
+import {Module, AttributeModel, ResourceInstance, PropertyModel, InputFEModel, OperationModel} from "../models";
import {ComponentInstanceFactory} from "./component-instance-factory";
import {InputBEModel, PropertyBEModel, RelationshipModel} from "app/models";
import { PolicyInstance } from "app/models/graph/zones/policy-instance";
@@ -126,5 +126,37 @@ export class CommonUtils {
return policies;
}
+
+ static initInterfaceOperations(interfaces: any): Array<OperationModel> {
+
+ return _.reduce(interfaces, (acc, interf: any) => {
+
+ return acc.concat(
+ _.map(interf.operations,
+ ({description, name, uniqueId, inputs, outputs}) => {
+ const operation = new OperationModel({
+ description,
+ operationType: name,
+ uniqueId
+ });
+ if (inputs) {
+ const inputParams = _.map(inputs.listToscaDataDefinition, (input:any) => {
+ return {paramName: input.name, paramId: input.inputId};
+ });
+ operation.createInputParamsList(inputParams);
+ }
+ if (outputs) {
+ const outputParams = _.map(outputs.listToscaDataDefinition, (output:any) => {
+ return {paramName: output.name, paramId: output.outputId};
+ });
+ operation.createOutputParamsList(outputParams);
+ }
+ return operation;
+ }
+ )
+ );
+
+ }, []);
+ }
}
diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts
index c8603424bb..9665999dcf 100644
--- a/catalog-ui/src/app/utils/constants.ts
+++ b/catalog-ui/src/app/utils/constants.ts
@@ -235,6 +235,7 @@ export class States {
public static WORKSPACE_INFORMATION_ARTIFACTS = 'workspace.information_artifacts';
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_NETWORK_CALL_FLOW = 'workspace.network_call_flow';
public static WORKSPACE_MANAGEMENT_WORKFLOW = 'workspace.management_workflow';
public static WORKSPACE_DEPLOYMENT = 'workspace.deployment';
@@ -318,7 +319,7 @@ export class COMPONENT_FIELDS {
static COMPONENT_TOSCA_ARTIFACTS = "toscaArtifacts";
static COMPONENT_POLICIES = "policies";
static COMPONENT_GROUPS = "groups";
-
+ static COMPONENT_INTERFACE_OPERATIONS = "interfaces";
}
export class SERVICE_FIELDS {
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view-model.ts
new file mode 100644
index 0000000000..1d42943fc9
--- /dev/null
+++ b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view-model.ts
@@ -0,0 +1,15 @@
+'use strict';
+
+import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model";
+
+export interface IInterfaceOperationViewModelScope extends IWorkspaceViewModelScope {};
+
+export class InterfaceOperationViewModel {
+
+ static '$inject' = [
+ '$scope'
+ ];
+
+ constructor(private $scope: IInterfaceOperationViewModelScope) {}
+
+}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view.html b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view.html
new file mode 100644
index 0000000000..b83c097c71
--- /dev/null
+++ b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation-view.html
@@ -0,0 +1,3 @@
+<div class="workspace-interface-operation">
+ <ng2-interface-operation [component]="component" [readonly]="isViewMode() || !isDesigner()"></ng2-interface-operation>
+</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation.less b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation.less
new file mode 100644
index 0000000000..abfe3f939e
--- /dev/null
+++ b/catalog-ui/src/app/view-models/workspace/tabs/interface-operation/interface-operation.less
@@ -0,0 +1,6 @@
+.workspace-interface-operation {
+ width: 100%;
+ display: inline-block;
+ top: -26px;
+ position: relative;
+}
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view-model.ts
index 3e0fb44cc8..1aff3db882 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view-model.ts
+++ b/catalog-ui/src/app/view-models/workspace/tabs/plugins/plugins-context-view-model.ts
@@ -48,11 +48,15 @@ export class PluginsContextViewModel {
uuid: this.$scope.component.uuid,
lifecycleState: this.$scope.component.lifecycleState,
isOwner: this.$scope.component.lastUpdaterUserId === this.$scope.user.userId,
- version: this.$scope.component.version ,
+ version: this.$scope.component.version,
parentUrl: window.location.origin,
eventsClientId: this.$scope.plugin.pluginId
};
+ if (this.$stateParams.queryParams) {
+ _.assign(this.$scope.queryParams, this.$stateParams.queryParams);
+ }
+
this.$scope.onLoadingDone = (plugin: Plugin) => {
if (plugin.pluginId == this.$scope.plugin.pluginId) {
this.$scope.isLoading = false;