diff options
author | aribeiro <anderson.ribeiro@est.tech> | 2022-01-13 14:33:25 +0000 |
---|---|---|
committer | Michael Morris <michael.morris@est.tech> | 2022-01-26 12:57:51 +0000 |
commit | c2fa1b7e8d43a236219d1f6ad2831de1af296cb4 (patch) | |
tree | c4ebc43f939b859ab5ef854d22d126961ee2e88c /catalog-ui/src/app/ng2/pages/interface-definition | |
parent | 7a98ee137b17a808635b06d72955e01ac84fe55b (diff) |
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
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/interface-definition')
4 files changed, 599 insertions, 0 deletions
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 @@ +<!-- + * ============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 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<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; + } + +} |