From c2fa1b7e8d43a236219d1f6ad2831de1af296cb4 Mon Sep 17 00:00:00 2001 From: aribeiro Date: Thu, 13 Jan 2022 14:33:25 +0000 Subject: View Interface definition on VFC Add Interface support to VFC view UI Issue-ID: SDC-3850 Signed-off-by: aribeiro Change-Id: Icd195c939af39d40ae8c617e740323dd3e70fc15 --- .../interface-operations.component.ts | 3 +- .../interface-operation-handler.component.html | 24 ++- .../interface-operation-handler.component.ts | 3 + .../interface-definition.module.ts | 47 +++++ .../interface-definition.page.component.html | 85 ++++++++ .../interface-definition.page.component.less | 234 +++++++++++++++++++++ .../interface-definition.page.component.ts | 233 ++++++++++++++++++++ 7 files changed, 619 insertions(+), 10 deletions(-) create mode 100644 catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.module.ts create mode 100644 catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.html create mode 100644 catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.less create mode 100644 catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.ts (limited to 'catalog-ui/src/app/ng2/pages') 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 2cc91a92a0..60d66788ac 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 @@ export class InterfaceOperationsComponent { 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 428c4cd5ed..6dec4160f6 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 @@ + [disabled]=isViewOnly> @@ -36,7 +36,7 @@ + [disabled]=isViewOnly> @@ -46,7 +46,8 @@ label="{{'OPERATION_DESCRIPTION' | translate}}" [(value)]="operationToUpdate.description" testId="interface-operation-description" - (valueChange)="onDescriptionChange($event)"> + (valueChange)="onDescriptionChange($event)" + [disabled]=isViewOnly> @@ -55,7 +56,8 @@
+ (checkedChange)="onMarkToAddArtifactToImplementation($event)" + [disabled]=isViewOnly>
@@ -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>
@@ -76,7 +79,8 @@ [selectedOption]="toscaArtifactTypeSelected" placeHolder="{{toscaArtifactTypeSelected != undefined ? toscaArtifactTypeSelected : 'Select...'}}" (changed)="onSelectToscaArtifactType($event)" - [options]="toscaArtifactTypes"> + [options]="toscaArtifactTypes" + [disabled]=isViewOnly>
@@ -85,7 +89,8 @@ data-tests-id="artifactFile" [(value)]="artifactName" [required]="true" - (valueChange)="onArtifactFileChange($event)"> + (valueChange)="onArtifactFileChange($event)" + [disabled]=isViewOnly>
@@ -93,7 +98,8 @@ label="{{ 'ARTIFACT_VERSION' | translate }}" data-tests-id="artifactVersion" [(value)]="artifactVersion" - (valueChange)="onArtifactVersionChange($event)"> + (valueChange)="onArtifactVersionChange($event)" + [disabled]=isViewOnly>
@@ -122,7 +128,7 @@ 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 6e4ae45487..1099391548 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 @@ export class InterfaceOperationHandlerComponent { selectedInterface: UIInterfaceModel; selectedInterfaceOperation: InterfaceOperationModel; validityChangedCallback: Function; + isViewOnly: boolean; }; interfaceType: string; @@ -60,6 +61,7 @@ export class InterfaceOperationHandlerComponent { properties: Array = []; isLoading: boolean = false; readonly: boolean; + isViewOnly: boolean; toscaArtifactTypeSelected: string; toscaArtifactTypeProperties: Array = []; @@ -70,6 +72,7 @@ export class InterfaceOperationHandlerComponent { 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 0000000000..27a7f111d2 --- /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 0000000000..25ccf111a1 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/interface-definition/interface-definition.page.component.html @@ -0,0 +1,85 @@ + +
+ +
+
+
{{ 'INTERFACE_DATA_EMPTY' | translate }}
+
+
+
+
+ + +
+
+ + + + + {{interface.type}} +
+ +
+
+ + {{ 'INTERFACE_HEADER_NAME' | translate }} + + + {{ 'INTERFACE_HEADER_DESCRIPTION' | translate }} + +
+ +
+ + {{operation.name}} + + + {{operation.getDescriptionEllipsis()}} + + {{!operation.isEllipsis ? '' : operation.isCollapsed ? 'More' : 'Less'}} + + +
+
+
+
+
+
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 0000000000..2b76c8c0ec --- /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 0000000000..2a77b5e996 --- /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; + interfaces: UIInterfaceModel[]; + inputs: Array = []; + + properties: Array = []; + deploymentArtifactsFilePath: Array = []; + + toscaArtifactTypes: Array = []; + + 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; + } + +} -- cgit 1.2.3-korg