X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=catalog-ui%2Fsrc%2Fapp%2Fng2%2Fpages%2Finterface-definition%2Finterface-definition.page.component.ts;h=90d6a6cfdee43e48d234064855dfebcdd09136d3;hb=4cbd35c09d849b29f2981ab18b8ef44b9c31a949;hp=2a77b5e996882e3a5707a5fb9bf5a5fca18849fe;hpb=c2fa1b7e8d43a236219d1f6ad2831de1af296cb4;p=sdc.git 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 index 2a77b5e996..90d6a6cfde 100644 --- 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 @@ -18,29 +18,37 @@ * 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 {Component, ComponentRef, Inject, Input} from '@angular/core'; +import {Component as IComponent} from 'app/models/components/component'; +import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service'; -import { SdcConfigToken, ISdcConfig } from "app/ng2/config/sdc-config.config"; -import {TranslateService } from "app/ng2/shared/translator/translate.service"; +import {ISdcConfig, SdcConfigToken} from "app/ng2/config/sdc-config.config"; +import {TranslateService} from "app/ng2/shared/translator/translate.service"; +import {IModalButtonComponent, SdcUiServices} from 'onap-ui-angular'; +import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component'; -import { ModalComponent } from 'app/ng2/components/ui/modal/modal.component'; -import {ModalService } from 'app/ng2/services/modal.service'; +import {ModalService} from 'app/ng2/services/modal.service'; import { - OperationModel, - InterfaceModel, + ArtifactModel, + ButtonModel, CapabilitiesGroup, - ButtonModel, ModalModel + InputBEModel, + InterfaceModel, + ModalModel, + OperationModel, + WORKFLOW_ASSOCIATION_OPTIONS } from 'app/models'; -import {ComponentServiceNg2 } from 'app/ng2/services/component-services/component.service'; - -import { SdcUiServices } from 'onap-ui-angular'; +import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service'; 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 {InterfaceOperationModel} from "../../../models/interfaceOperation"; import {InterfaceOperationHandlerComponent} from "../composition/interface-operatons/operation-creator/interface-operation-handler.component"; import {DropdownValue} from "../../components/ui/form-components/dropdown/ui-element-dropdown.component"; +import {ToscaArtifactModel} from "../../../models/toscaArtifact"; +import {ToscaArtifactService} from "../../services/tosca-artifact.service"; +import {InterfaceOperationComponent} from "../interface-operation/interface-operation.page.component"; +import {Observable} from "rxjs/Observable"; +import {PluginsService} from 'app/ng2/services/plugins.service'; export class UIOperationModel extends OperationModel { isCollapsed: boolean = true; @@ -49,7 +57,6 @@ export class UIOperationModel extends OperationModel { constructor(operation: OperationModel) { super(operation); - if (!operation.description) { this.description = ''; } @@ -74,7 +81,6 @@ export class UIOperationModel extends OperationModel { } } -// tslint:disable-next-line:max-classes-per-file class ModalTranslation { CREATE_TITLE: string; EDIT_TITLE: string; @@ -99,16 +105,14 @@ class ModalTranslation { } } -// 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) - ); + constructor(interf?: any) { + super(interf); + if (this.operations) { + this.operations = this.operations.map((operation) => new UIOperationModel(operation)); + } } toggleCollapse() { @@ -116,24 +120,23 @@ export class UIInterfaceModel extends InterfaceModel { } } -// 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] + providers: [ModalService, TranslateService, InterfaceOperationComponent] }) - export class InterfaceDefinitionComponent { modalInstance: ComponentRef; interfaces: UIInterfaceModel[]; - inputs: Array = []; + inputs: InputBEModel[]; - properties: Array = []; deploymentArtifactsFilePath: Array = []; toscaArtifactTypes: Array = []; + interfaceTypesTest: Array = []; + interfaceTypesMap: Map; isLoading: boolean; interfaceTypes: { [interfaceType: string]: string[] }; @@ -141,6 +144,11 @@ export class InterfaceDefinitionComponent { workflows: any[]; capabilities: CapabilitiesGroup; + openOperation: OperationModel; + enableWorkflowAssociation: boolean; + workflowIsOnline: boolean; + validImplementationProps:boolean = true; + @Input() component: IComponent; @Input() readonly: boolean; @Input() enableMenuItems: Function; @@ -149,18 +157,59 @@ export class InterfaceDefinitionComponent { constructor( @Inject(SdcConfigToken) private sdcConfig: ISdcConfig, @Inject("$state") private $state: ng.ui.IStateService, + @Inject("Notification") private notification: any, private translateService: TranslateService, private componentServiceNg2: ComponentServiceNg2, private modalServiceNg2: ModalService, private modalServiceSdcUI: SdcUiServices.ModalService, - private topologyTemplateService: TopologyTemplateService + private topologyTemplateService: TopologyTemplateService, + private toscaArtifactService: ToscaArtifactService, + private ComponentServiceNg2: ComponentServiceNg2, + private WorkflowServiceNg2: WorkflowServiceNg2, + private ModalServiceSdcUI: SdcUiServices.ModalService, + private PluginsService: PluginsService ) { this.modalTranslation = new ModalTranslation(translateService); + this.interfaceTypesMap = new Map(); } ngOnInit(): void { - if(this.component) { - this.initInterfaceDefinition(); + this.isLoading = true; + this.interfaces = []; + this.workflowIsOnline = !_.isUndefined(this.PluginsService.getPluginByStateUrl('workflowDesigner')); + Observable.forkJoin( + this.ComponentServiceNg2.getInterfaceOperations(this.component), + this.ComponentServiceNg2.getComponentInputs(this.component), + this.ComponentServiceNg2.getInterfaceTypes(this.component), + this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.component.componentType, this.component.uniqueId) + ).subscribe((response: any[]) => { + const callback = (workflows) => { + this.isLoading = false; + this.initInterfaces(response[0].interfaces); + this.sortInterfaces(); + this.inputs = response[1].inputs; + this.interfaceTypes = response[2]; + this.workflows = (workflows.items) ? workflows.items : workflows; + this.capabilities = response[3].capabilities; + }; + if (this.enableWorkflowAssociation && this.workflowIsOnline) { + this.WorkflowServiceNg2.getWorkflows().subscribe( + callback, + (err) => { + this.workflowIsOnline = false; + callback([]); + } + ); + } else { + callback([]); + } + }); + this.loadToscaArtifacts(); + } + + initInterfaces(interfaces: InterfaceModel[]): void { + if (interfaces) { + this.interfaces = interfaces.map((interf) => new UIInterfaceModel(interf)); } } @@ -168,16 +217,43 @@ export class InterfaceDefinitionComponent { return this.modalServiceNg2.closeCurrentModal(); } - private enableOrDisableSaveButton = (): boolean => { - return true; + private disableSaveButton = (): boolean => { + let disable:boolean = true; + if(this.readonly) { + return disable; + } + + let selectedInterfaceOperation = this.modalInstance.instance.dynamicContent.instance.selectedInterfaceOperation; + let isInterfaceOperation:boolean = !(typeof selectedInterfaceOperation == 'undefined' || _.isEmpty(selectedInterfaceOperation)); + let selectedInterfaceType = this.modalInstance.instance.dynamicContent.instance.selectedInterfaceType; + let isInterfaceType:boolean = !(typeof selectedInterfaceType == 'undefined' || _.isEmpty(selectedInterfaceType)); + let bothSet: boolean = isInterfaceOperation && isInterfaceType; + + let enableAddArtifactImplementation = this.modalInstance.instance.dynamicContent.instance.enableAddArtifactImplementation; + if(enableAddArtifactImplementation) { + let validImplementationProps = this.modalInstance.instance.dynamicContent.instance.validImplementationProps; + let toscaArtifactTypeSelected = this.modalInstance.instance.dynamicContent.instance.toscaArtifactTypeSelected; + let isToscaArtifactType:boolean = !(typeof toscaArtifactTypeSelected == 'undefined' || _.isEmpty(toscaArtifactTypeSelected)); + disable = !bothSet || !isToscaArtifactType || !validImplementationProps; + return disable; + } + disable = !bothSet; + return disable; } 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 isEdit = operation !== undefined; + const modalButtons = []; + if (!this.readonly) { + const saveButton: ButtonModel = new ButtonModel(this.modalTranslation.SAVE_BUTTON, 'blue', + () => isEdit ? this.updateOperation() : this.createOperationCallback(), + this.disableSaveButton + ); + modalButtons.push(saveButton); + } + modalButtons.push(new ButtonModel(this.modalTranslation.CANCEL_BUTTON, 'outline white', this.cancelAndCloseModal)); const interfaceDataModal: ModalModel = - new ModalModel('l', this.modalTranslation.EDIT_TITLE, '', [saveButton, cancelButton], 'custom'); + new ModalModel('l', this.modalTranslation.EDIT_TITLE, '', modalButtons, 'custom'); this.modalInstance = this.modalServiceNg2.createCustomModal(interfaceDataModal); this.modalServiceNg2.addDynamicContentToModal( @@ -186,39 +262,152 @@ export class InterfaceDefinitionComponent { { deploymentArtifactsFilePath: this.deploymentArtifactsFilePath, toscaArtifactTypes: this.toscaArtifactTypes, - selectedInterface: interfaceModel, - selectedInterfaceOperation: operation, - validityChangedCallback: this.enableOrDisableSaveButton, - isViewOnly: true + selectedInterface: interfaceModel ? interfaceModel : new UIInterfaceModel(), + selectedInterfaceOperation: operation ? operation : new InterfaceOperationModel(), + validityChangedCallback: this.disableSaveButton, + isViewOnly: this.readonly, + validImplementationProps: this.validImplementationProps, + 'isEdit': isEdit, + interfaceTypesMap: this.interfaceTypesMap, + modelName: this.component.model } ); this.modalInstance.instance.open(); } + private updateOperation = (): void => { + this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = true; + const interfaceOperationHandlerComponentInstance: InterfaceOperationHandlerComponent = this.modalInstance.instance.dynamicContent.instance; + const operationToUpdate = this.modalInstance.instance.dynamicContent.instance.operationToUpdate; + let timeout = null; + if (operationToUpdate.implementation && operationToUpdate.implementation.timeout != null) { + timeout = operationToUpdate.implementation.timeout; + } + const isArtifactChecked = interfaceOperationHandlerComponentInstance.enableAddArtifactImplementation; + if (!isArtifactChecked) { + const artifactName = interfaceOperationHandlerComponentInstance.artifactName ? + interfaceOperationHandlerComponentInstance.artifactName : ''; + operationToUpdate.implementation = new ArtifactModel({'artifactName': artifactName, 'artifactVersion': ''} as ArtifactModel); + } + if (timeout != null) { + operationToUpdate.implementation.timeout = timeout; + } + this.componentServiceNg2.updateComponentInterfaceOperation(this.component.uniqueId, operationToUpdate) + .subscribe((newOperation: InterfaceOperationModel) => { + let oldOpIndex; + let oldInterf; + this.interfaces.forEach(interf => { + interf.operations.forEach(op => { + if (op.uniqueId === newOperation.uniqueId) { + oldInterf = interf; + oldOpIndex = interf.operations.findIndex((el) => el.uniqueId === op.uniqueId); + } + }); + }); + oldInterf.operations.splice(oldOpIndex, 1); + oldInterf.operations.push(new InterfaceOperationModel(newOperation)); + }, error => { + this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false; + }, () => { + this.sortInterfaces(); + this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false; + this.modalServiceNg2.closeCurrentModal(); + }); + } + + private createOperationCallback(): void { + this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = true; + const operationToUpdate = this.modalInstance.instance.dynamicContent.instance.operationToUpdate; + console.log('createOperationCallback', operationToUpdate); + console.log('this.component', this.component); + this.componentServiceNg2.createComponentInterfaceOperation(this.component.uniqueId, this.component.getTypeUrl(), operationToUpdate) + .subscribe((newOperation: InterfaceOperationModel) => { + const foundInterface = this.interfaces.find(value => value.type === newOperation.interfaceType); + if (foundInterface) { + foundInterface.operations.push(new UIOperationModel(new OperationModel(newOperation))); + } else { + const uiInterfaceModel = new UIInterfaceModel(); + uiInterfaceModel.type = newOperation.interfaceType; + uiInterfaceModel.uniqueId = newOperation.interfaceType; + uiInterfaceModel.operations = []; + uiInterfaceModel.operations.push(new UIOperationModel(new OperationModel(newOperation))); + this.interfaces.push(uiInterfaceModel); + } + }, error => { + this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false; + }, () => { + this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false; + this.modalServiceNg2.closeCurrentModal(); + }); + } + + private handleEnableAddArtifactImplementation = (newOperation: InterfaceOperationModel): InterfaceOperationModel => { + if (!this.isEnableAddArtifactImplementation()) { + newOperation.implementation.artifactType = null; + newOperation.implementation.artifactVersion = null; + } + return newOperation; + } + + private isEnableAddArtifactImplementation = (): boolean => { + return this.modalInstance.instance.dynamicContent.enableAddArtifactImplementation; + } + 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.interfaces = response.interfaces.map((interfaceModel) => new UIInterfaceModel(interfaceModel)); } this.isLoading = false; }); } + private loadToscaArtifacts() { + this.toscaArtifactService.getToscaArtifacts(this.component.model).subscribe(response => { + if (response) { + let toscaArtifactsFound = _.values(response); + toscaArtifactsFound.forEach(value => this.toscaArtifactTypes.push(new DropdownValue(value, value.type))); + } + }, error => { + this.notification.error({ + message: 'Failed to Load Tosca Artifacts:' + error, + title: 'Failure' + }); + }); + } + + private loadInterfaceTypes() { + this.componentServiceNg2.getInterfaceTypes(this.component).subscribe(response => { + if (response) { + console.info("loadInterfaceTypes ", response); + for (const interfaceType in response) { + this.interfaceTypesMap.set(interfaceType, response[interfaceType]); + this.interfaceTypesTest.push(new DropdownValue(interfaceType, interfaceType)); + } + } + }, error => { + this.notification.error({ + message: 'Failed to Load Interface Types:' + error, + title: 'Failure' + }); + }); + } + collapseAll(value: boolean = true): void { - _.forEach(this.interfaces, (interfaceData) => { + this.interfaces.forEach(interfaceData => { interfaceData.isCollapsed = value; }); } isAllCollapsed(): boolean { - return _.every(this.interfaces, (interfaceData) => interfaceData.isCollapsed); + return this.interfaces.every((interfaceData) => interfaceData.isCollapsed); } isAllExpanded(): boolean { - return _.every(this.interfaces, (interfaceData) => !interfaceData.isCollapsed); + return this.interfaces.every((interfaceData) => !interfaceData.isCollapsed); } isInterfaceListEmpty(): boolean { @@ -226,8 +415,94 @@ export class InterfaceDefinitionComponent { } isOperationListEmpty(): boolean { - return _.filter(this.interfaces, (interfaceData) => - interfaceData.operations && interfaceData.operations.length > 0).length > 0; + return this.interfaces.filter((interfaceData) => interfaceData.operations && interfaceData.operations.length > 0).length > 0; + } + + onRemoveOperation(operation: OperationModel): void { + if (this.readonly) { + return; + } + + const deleteButton: IModalButtonComponent = { + id: 'deleteButton', + text: this.modalTranslation.DELETE_BUTTON, + type: 'primary', + size: 'small', + closeModal: true, + callback: () => { + this.ComponentServiceNg2 + .deleteInterfaceOperation(this.component, operation) + .subscribe(() => { + const curInterf = this.interfaces.find((interf) => interf.type === operation.interfaceType); + const index = curInterf.operations.findIndex((el) => el.uniqueId === operation.uniqueId); + curInterf.operations.splice(index, 1); + if (!curInterf.operations.length) { + const interfIndex = this.interfaces.findIndex((interf) => interf.type === operation.interfaceType); + this.interfaces.splice(interfIndex, 1); + } + }); + } + }; + + const cancelButton: IModalButtonComponent = { + id: 'cancelButton', + text: this.modalTranslation.CANCEL_BUTTON, + type: 'secondary', + size: 'small', + closeModal: true, + callback: () => { + this.openOperation = null; + }, + }; + + this.ModalServiceSdcUI.openWarningModal( + this.modalTranslation.DELETE_TITLE, + this.modalTranslation.deleteText(operation.name), + 'deleteOperationModal', + [deleteButton, cancelButton], + ); + } + + private createOperation = (operation: OperationModel): void => { + this.ComponentServiceNg2.createInterfaceOperation(this.component, operation).subscribe((response: OperationModel) => { + this.openOperation = null; + + let curInterf = this.interfaces.find((interf) => interf.type === operation.interfaceType); + + if (!curInterf) { + curInterf = new UIInterfaceModel({ + type: response.interfaceType, + uniqueId: response.uniqueId, + operations: [] + }); + this.interfaces.push(curInterf); + } + + const newOpModel = new UIOperationModel(response); + curInterf.operations.push(newOpModel); + this.sortInterfaces(); + + if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL && operation.artifactData) { + this.ComponentServiceNg2.uploadInterfaceOperationArtifact(this.component, newOpModel, operation).subscribe(); + } else if (response.workflowId && operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING) { + this.WorkflowServiceNg2.associateWorkflowArtifact(this.component, response).subscribe(); + } else if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.NEW) { + this.$state.go('workspace.plugins', {path: 'workflowDesigner'}); + } + }); + } + + private enableOrDisableSaveButton = (shouldEnable: boolean): void => { + const saveButton = this.modalInstance.instance.dynamicContent.getButtonById('saveButton'); + saveButton.disabled = !shouldEnable; + } + + private sortInterfaces(): void { + this.interfaces = this.interfaces.filter((interf) => interf.operations && interf.operations.length > 0); // remove empty interfaces + this.interfaces.sort((a, b) => a.type.localeCompare(b.type)); // sort interfaces alphabetically + this.interfaces.forEach((interf) => { + interf.operations.sort((a, b) => a.name.localeCompare(b.name)); // sort operations alphabetically + }); } }