diff options
author | vasraz <vasyl.razinkov@est.tech> | 2021-02-16 17:37:57 +0000 |
---|---|---|
committer | Christophe Closset <christophe.closset@intl.att.com> | 2021-02-17 15:57:55 +0000 |
commit | 26e5029d922779fd7e786c1a31b6b37492132388 (patch) | |
tree | 8e8e68a6913749e1405fce951bc7816d4fa35ba3 /catalog-ui/src/app/ng2/components/logic/outputs-table | |
parent | f2c0a4118c3c0b6360b639622766543bd754b59c (diff) |
Implement Attributes/Outputs FE
Change-Id: I014bb0ebc07f3fea4266a4f295172eadee546705
Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech>
Issue-ID: SDC-3448
Diffstat (limited to 'catalog-ui/src/app/ng2/components/logic/outputs-table')
3 files changed, 427 insertions, 0 deletions
diff --git a/catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.html b/catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.html new file mode 100644 index 0000000000..fbae0e45e6 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.html @@ -0,0 +1,97 @@ +<!-- +============LICENSE_START======================================================= +* Copyright (C) 2021 Nordix Foundation +* ================================================================================ +* 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========================================================= +--> + +<div class="output-attributes-table"> + <loader [display]="isLoading" [size]="'large'" [relative]="true"></loader> + <div class="table-header"> + <div class="table-cell col-output-attribute-name" (click)="sort('name')">Output Name + <span *ngIf="sortBy === 'name'" class="table-header-sort-arrow" + [ngClass]="{'down': reverse, 'up':!reverse}"></span> + </div> + <div class="table-cell col-output-attribute-instance" (click)="sort('instanceUniqueId')">From + Instance + <span *ngIf="sortBy === 'instanceUniqueId'" class="table-header-sort-arrow" + [ngClass]="{'down': reverse, 'up':!reverse}"></span> + </div> + <div class="table-cell col-output-attribute-type" (click)="sort('type')">Type + <span *ngIf="sortBy === 'type'" class="table-header-sort-arrow" + [ngClass]="{'down': reverse, 'up':!reverse}"> + </span> + </div> + <div class="table-cell col-output-attribute-required" (click)="sort('required')" + *ngIf="componentType == 'SERVICE'"> + <span tooltip="Required in Runtime" tooltipDelay="400">Req. in RT</span> + </div> + <div class="table-cell col-output-attribute-value">Value</div> + </div> + <div class="table-body"> + <div class="no-data" *ngIf="!outputs || !outputs.length">No data to display</div> + <div> + <div class="table-row" *ngFor="let output of outputs"> + <!-- attribute Name --> + <div class="table-cell col-output-attribute-name"> + <div class="output-inner-cell-div"> + <span class="attribute-name" tooltip="{{output.name}}">{{output.name}}</span> + </div> + <span *ngIf="output.description" + class="attribute-description-icon sprite-new show-desc" + tooltip="{{output.description}}" tooltipDelay="0"></span> + </div> + <!-- From Instance --> + <div class="table-cell col-output-attribute-instance"> + <div class="output-inner-cell-div" + tooltip="{{instanceNamesMap[output.instanceUniqueId]?.name}}"> + <span>{{instanceNamesMap[output.instanceUniqueId]?.name}}</span> + </div> + </div> + <!-- Type --> + <div class="table-cell col-output-attribute-type"> + <div class="output-inner-cell-div" tooltip="{{output.type | contentAfterLastDot}}"> + <span>{{output.type | contentAfterLastDot}}</span> + </div> + </div> + <!-- Required in runtime --> + <div class="table-cell col-output-attribute-required" *ngIf="componentType == 'SERVICE'"> + <sdc-checkbox [(checked)]="output.required" + (checkedChange)="onRequiredChanged(output, $event)" + [disabled]="readonly"></sdc-checkbox> + </div> + <!-- Value --> + <div class="table-cell col-output-attribute-value output-value-col" + [class.inner-table-container]="!output.isSimpleType"> + <dynamic-element class="value-output" + *ngIf="checkInstanceFeAttributesMapIsFilled() && output.isSimpleType" + pattern="null" + [value]="output.value" + [type]="'string'" + [name]="output.name" + (elementChanged)="onOutputChanged(output, $event)" + [readonly]="true" + [testId]="'output-' + output.name" + [constraints]="getConstraints(output)"> + </dynamic-element> + <div class="delete-button-container"> + <span *ngIf="output.instanceUniqueId && !readonly" class="sprite-new delete-btn" + (click)="openDeleteModal(output)"></span> + </div> + </div> + </div> + </div> + </div> +</div> diff --git a/catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.less b/catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.less new file mode 100644 index 0000000000..56ed502943 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.less @@ -0,0 +1,189 @@ +@import './../../../../../assets/styles/variables.less'; + +:host /deep/ output { + width: 100%; +} + +.output-attributes-table { + display: flex; + flex-direction: column; + flex: 1; + height: 100%; + text-align: left; + + .output-inner-cell-div { + max-width: 100%; + text-overflow: ellipsis; + overflow: hidden; + height: 20px; + } + + + .table-header { + font-weight: bold; + border-top: #d2d2d2 solid 1px; + background-color: #eaeaea; + color: #191919; + + .table-cell { + font-size: 13px; + + .table-header-sort-arrow { + display: inline-block; + background-color: transparent; + border: none; + color: #AAA; + margin: 8px 0 0 5px; + + &.up { + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid; + } + + &.down { + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid; + } + } + } + + .output-value-col { + justify-content: flex-start; + padding: 10px; + } + } + + .table-header, .table-row { + display: flex; + flex-direction: row; + flex: 0 0 auto; + } + + .table-body { + display: flex; + flex-direction: column; + overflow-y: auto; + flex: 1; + + .no-data { + border: #d2d2d2 solid 1px; + border-top: none; + text-align: center; + height: 100%; + padding: 20px; + } + + /deep/ .selected { + background-color: #e6f6fb; + color: #009fdb; + } + } + + .table-row { + &:hover { + background-color: #f8f8f8; + cursor: pointer; + } + + &:last-child { + flex: 1 0 auto; + } + + .selected-row { + background-color: #e6f6fb; + } + } + + .table-cell { + font-size: 13px; + flex: 1; + border: #d2d2d2 solid 1px; + border-right: none; + border-top: none; + padding: 10px; + text-overflow: ellipsis; + white-space: nowrap; + + + &:last-child { + border-right: #d2d2d2 solid 1px; + } + + &.col-output-attribute-name { + flex: 1 0 130px; + max-width: 250px; + + justify-content: space-between; + + .property-name { + flex: 1; + } + + .property-description-icon { + float: right; + margin-top: 4px; + margin-left: 5px; + flex: 0 0 auto; + } + } + + &.col-output-attribute-type { + flex: 0 0 140px; + max-width: 140px; + } + + &.col-output-attribute-instance { + flex: 0 0 120px; + max-width: 120px; + } + + &.col-output-attribute-required { + flex: 0 0 80px; + max-width: 80px; + text-align: center; + } + + &.col-output-attribute-value { + .value-output { + flex: 1; + border: none; + background-color: inherit; + + &:focus, &:active { + border: none; + outline: none; + } + } + + .delete-btn { + flex: 0 0 auto; + } + + .delete-button-container { + max-height: 24px; + } + + &.inner-table-container { + padding: 0; + + .delete-button-container { + padding: 0 8px 0 0; + } + } + } + + &.output-value-col { + padding: 8px; + } + + } + + .filtered { + /deep/ .checkbox-label-content { + background-color: yellow; + } + } + +} diff --git a/catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.ts b/catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.ts new file mode 100644 index 0000000000..a7caeaa9fb --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.ts @@ -0,0 +1,141 @@ +/* +* ============LICENSE_START======================================================= +* Copyright (C) 2021 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, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core'; +import {InstanceFeDetails} from "../../../../models/instance-fe-details"; +import {ModalService} from "../../../services/modal.service"; +import {DataTypeService} from "../../../services/data-type.service"; +import {TranslateService} from "../../../shared/translator/translate.service"; +import {InstanceFeAttributesMap} from "app/models/attributes-outputs/attribute-fe-map"; +import {Select} from "@ngxs/store"; +import {WorkspaceState} from "../../../store/states/workspace.state"; +import {OutputFEModel} from "app/models/attributes-outputs/output-fe-model"; +import {InputFEModel} from "../../../../models/properties-inputs/input-fe-model"; + +@Component({ + selector: 'outputs-table', + templateUrl: './outputs-table.component.html', + styleUrls: ['./outputs-table.component.less'] +}) +export class OutputsTableComponent implements OnInit { + @Select(WorkspaceState.isViewOnly) + isViewOnly$: boolean; + + @ViewChild('componentOutputsTable') + private table: any; + + @Input() outputs: Array<OutputFEModel>; + @Input() instanceNamesMap: Map<string, InstanceFeDetails>; + @Input() readonly: boolean; + @Input() isLoading: boolean; + @Input() componentType: string; + @Output() outputChanged: EventEmitter<any> = new EventEmitter<any>(); + @Output() deleteOutput: EventEmitter<any> = new EventEmitter<any>(); + @Input() feAttributesMap: InstanceFeAttributesMap; + + deleteMsgTitle: string; + deleteMsgBodyTxt: string; + modalDeleteBtn: string; + modalCancelBtn: string; + sortBy: string; + reverse: boolean; + selectedOutputToDelete: OutputFEModel; + + constructor(private modalService: ModalService, + private dataTypeService: DataTypeService, + private translateService: TranslateService) { + } + + ngOnInit() { + this.translateService.languageChangedObservable.subscribe((lang) => { + this.deleteMsgTitle = this.translateService.translate('DELETE_OUTPUT_TITLE'); + this.modalDeleteBtn = this.translateService.translate('MODAL_DELETE'); + this.modalCancelBtn = this.translateService.translate('MODAL_CANCEL'); + + }); + } + + sort = (sortBy) => { + this.reverse = (this.sortBy === sortBy) ? !this.reverse : true; + let reverse = this.reverse ? 1 : -1; + this.sortBy = sortBy; + let instanceNameMapTemp = this.instanceNamesMap; + let itemIdx1Val = ""; + let itemIdx2Val = ""; + this.outputs.sort(function (itemIdx1, itemIdx2) { + if (sortBy == 'instanceUniqueId') { + itemIdx1Val = (itemIdx1[sortBy] && instanceNameMapTemp[itemIdx1[sortBy]] !== undefined) ? instanceNameMapTemp[itemIdx1[sortBy]].name : ""; + itemIdx2Val = (itemIdx2[sortBy] && instanceNameMapTemp[itemIdx2[sortBy]] !== undefined) ? instanceNameMapTemp[itemIdx2[sortBy]].name : ""; + } else { + itemIdx1Val = itemIdx1[sortBy]; + itemIdx2Val = itemIdx2[sortBy]; + } + if (itemIdx1Val < itemIdx2Val) { + return -1 * reverse; + } else if (itemIdx1Val > itemIdx2Val) { + return 1 * reverse; + } else { + return 0; + } + }); + }; + + onOutputChanged = (output, event) => { + output.updateDefaultValueObj(event.value, event.isValid); + this.outputChanged.emit(output); + }; + + onRequiredChanged = (output: OutputFEModel, event) => { + this.outputChanged.emit(output); + } + + onDeleteOutput = () => { + this.deleteOutput.emit(this.selectedOutputToDelete); + this.modalService.closeCurrentModal(); + }; + + openDeleteModal = (output: OutputFEModel) => { + this.selectedOutputToDelete = output; + this.modalService.createActionModal("Delete Output", "Are you sure you want to delete this output?", "Delete", this.onDeleteOutput, "Close").instance.open(); + } + + getConstraints(output: OutputFEModel): string[] { + if (output.outputPath) { + const pathValuesName = output.outputPath.split('#'); + const rootPropertyName = pathValuesName[0]; + const propertyName = pathValuesName[1]; + let filteredRootPropertyType = _.values(this.feAttributesMap)[0].filter(property => + property.name == rootPropertyName); + if (filteredRootPropertyType.length > 0) { + let rootPropertyType = filteredRootPropertyType[0].type; + return this.dataTypeService.getConstraintsByParentTypeAndUniqueID(rootPropertyType, propertyName); + } else { + return null; + } + + } else { + return null; + } + } + + checkInstanceFeAttributesMapIsFilled() { + return _.keys(this.feAttributesMap).length > 0 + } + +} |