From 26e5029d922779fd7e786c1a31b6b37492132388 Mon Sep 17 00:00:00 2001 From: vasraz Date: Tue, 16 Feb 2021 17:37:57 +0000 Subject: Implement Attributes/Outputs FE Change-Id: I014bb0ebc07f3fea4266a4f295172eadee546705 Signed-off-by: Vasyl Razinkov Issue-ID: SDC-3448 --- .../attributes-table/attribute-table.module.ts | 49 ++++ .../attributes-table.component.html | 97 ++++++++ .../attributes-table.component.less | 264 +++++++++++++++++++++ .../attributes-table.component.spec.ts | 190 +++++++++++++++ .../attributes-table/attributes-table.component.ts | 116 +++++++++ .../dynamic-attribute.component.html | 102 ++++++++ .../dynamic-attribute.component.less | 82 +++++++ .../dynamic-attribute.component.ts | 232 ++++++++++++++++++ .../pipes/filterChildAttributes.pipe.ts | 38 +++ .../hierarchy-navigation.module.ts | 32 +++ .../outputs-table/outputs-table.component.html | 97 ++++++++ .../outputs-table/outputs-table.component.less | 189 +++++++++++++++ .../logic/outputs-table/outputs-table.component.ts | 141 +++++++++++ .../properties-table/properties-table.component.ts | 1 - 14 files changed, 1629 insertions(+), 1 deletion(-) create mode 100644 catalog-ui/src/app/ng2/components/logic/attributes-table/attribute-table.module.ts create mode 100644 catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.html create mode 100644 catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.less create mode 100644 catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.spec.ts create mode 100644 catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.ts create mode 100644 catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.html create mode 100644 catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.less create mode 100644 catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.ts create mode 100644 catalog-ui/src/app/ng2/components/logic/attributes-table/pipes/filterChildAttributes.pipe.ts create mode 100644 catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.module.ts create mode 100644 catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.html create mode 100644 catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.less create mode 100644 catalog-ui/src/app/ng2/components/logic/outputs-table/outputs-table.component.ts (limited to 'catalog-ui/src/app/ng2/components') diff --git a/catalog-ui/src/app/ng2/components/logic/attributes-table/attribute-table.module.ts b/catalog-ui/src/app/ng2/components/logic/attributes-table/attribute-table.module.ts new file mode 100644 index 0000000000..5f4b15781a --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/attributes-table/attribute-table.module.ts @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import {NgModule} from "@angular/core"; +import {AttributesTableComponent} from "./attributes-table.component"; +import {DynamicAttributeComponent} from "./dynamic-attribute/dynamic-attribute.component"; +import {FormsModule} from "@angular/forms"; +import {UiElementsModule} from "../../ui/ui-elements.module"; +import {CommonModule} from "@angular/common"; +import {FilterChildAttributesPipe} from "./pipes/filterChildAttributes.pipe"; +import {GlobalPipesModule} from "../../../pipes/global-pipes.module"; +import {MultilineEllipsisModule} from "../../../shared/multiline-ellipsis/multiline-ellipsis.module"; +import {AttributesService} from "../../../services/attributes.service"; + +@NgModule({ + imports: [ + FormsModule, + CommonModule, + GlobalPipesModule, + UiElementsModule, + MultilineEllipsisModule + ], + declarations: [ + FilterChildAttributesPipe, + DynamicAttributeComponent, + AttributesTableComponent + ], + exports: [AttributesTableComponent, DynamicAttributeComponent], + providers: [FilterChildAttributesPipe, AttributesService] +}) +export class AttributeTableModule { +} \ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.html b/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.html new file mode 100644 index 0000000000..1115620594 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.html @@ -0,0 +1,97 @@ + + +
+ +
+
Attribute Name + + +
+
Type + + +
+
EntrySchema + + +
+
Value
+
+
+
No data to display
+ + + +
+ + {{feInstanceNamesMap[instanceId].name}} +
+
+ +
+ +
+ +
+ +
+ {{property.name}} +
+
+ +
+ +
+
+ {{property.type | contentAfterLastDot}} +
+
+ +
+
+ {{property.schema.property.type | contentAfterLastDot}} +
+
+ +
+ + +
+
+
+ +
+
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.less b/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.less new file mode 100644 index 0000000000..26ae0d4d74 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.less @@ -0,0 +1,264 @@ +@import './../../../../../assets/styles/mixins.less'; +@import '../../../../../assets/styles/sprite'; +@smaller-screen: ~"only screen and (max-width: 1580px)"; + +:host /deep/ input { width:100%;} + +.attributes-table { + display: flex; + flex-direction: column; + flex: 1; + height: 100%; + text-align: left; + + + .inner-cell-div { + text-overflow: ellipsis; + overflow: hidden; + height: 20px; + } + + .inner-cell-div-multiline { + max-width: 100%; + } + + .table-header { + display: flex; + flex-direction:row; + flex: 0 0 auto; + font-weight:bold; + border-top: #d2d2d2 solid 1px; + background-color: #f2f2f2; + + .table-cell { + color:#191919; + 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; + height:5px; + } + &.down { + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid; + } + } + } + } + + .table-rows-header { + border: #d2d2d2 solid 1px; + border-top:none; + display: flex; + align-items: center; + .archive-label{ + margin-left: 10px; + } + } + + .table-body { + display:flex; + flex-direction: column; + overflow-y:auto; + flex: 1; + background-color: @main_color_p; + + .no-data { + border: #d2d2d2 solid 1px; + border-top:none; + text-align: center; + height: 100%; + padding: 20px; + } + /deep/.selected{ + background-color: #e6f6fb; + color: #009fdb; + } + &.view-mode{ + /deep/ .dynamic-property-row:not(.selected){ + background-color:#f8f8f8; + } + } + .table-row { + display: flex; + flex-direction:row; + flex: 0 0 auto; + &.readonly{ + background-color: #f8f8f8; + cursor: auto; + } + + &:hover:not(.selected){ + background-color:#f8f8f8; cursor:pointer; + /deep/ .dynamic-property-row:not(.selected){ + background-color:#f8f8f8; cursor:pointer; + } + } + + .selected-row { + background-color:#e6f6fb; + } + + .table-cell.valueCol { + padding:0px; + + } + } + } + .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; + overflow:hidden; + display: flex; + min-height:40px; + + &:last-child { + border-right:#d2d2d2 solid 1px; + } + + // Column: Property Name + &.col1 { + flex: 1 0 190px; + max-width:300px; + display: flex; + @media @smaller-screen { flex: 0 0 25%;} + + .attribute-name { + flex: 1; + display: flex; + overflow: hidden; + //max-width: 90%; fix bug 327139 + } + + .property-description-icon { + float: right; + margin-top: 4px; + margin-left: 15px; + flex: 0 0 auto; + } + } + + // Column: Type + &.col2 { + flex: 0 0 150px; + max-width:150px; + @media @smaller-screen { flex: 0 0 20%;} + } + + // Column: ES + &.col3 { + flex:0 0 120px; + max-width:120px; + @media @smaller-screen { flex: 0 0 15%;} + } + + // Column: Value + &.valueCol { + flex: 2 0 250px; + display: flex; + @media @smaller-screen { flex: 1 0 40%;} + } + + + /deep/ .checkbox-container { + margin-right: 10px; + } + + /deep/ &.round-checkbox { + .checkbox-container input[type=checkbox].checkbox-hidden { + &:checked ~ .checkbox-icon::before { + .sprite-new; + .round-checked-icon; + } + &[disabled] ~ .checkbox-icon::before { + .sprite-new; + .round-checked-icon.disabled; + background-color:inherit; + border:none; + //animation: addDisabledCheck 4s linear; + } + } + } + } + + .delete-button-container { + max-height: 24px; + cursor: pointer; + } + + .filtered { + /deep/ .checkbox-label-content{ + background-color: yellow; + } + } + + dynamic-property { + width:100%; + &:last-child /deep/ .dynamic-property-row { + border-bottom:none; + } + } + + .table-row { + /deep/ .table-cell-multiline-ellipsis .multiline-ellipsis-dots { + background: linear-gradient(to right, transparent 0%, #ffffff 80%); + padding-left: 1em; + } + + &.selected /deep/ .table-cell-multiline-ellipsis .multiline-ellipsis-dots { + background: linear-gradient(to right, transparent 0%, #e6f6fb 80%); + padding-left: 1em; + } + + &.readonly /deep/ .table-cell-multiline-ellipsis .multiline-ellipsis-dots { + background: linear-gradient(to right, transparent 0%, #f8f8f8 80%); + padding-left: 1em; + } + + &:hover:not(.selected) /deep/ .table-cell-multiline-ellipsis .multiline-ellipsis-dots { + background: linear-gradient(to right, transparent 0%, #f8f8f8 80%); + padding-left: 1em; + } + } + + .prop-instance-icon { + vertical-align: middle; + margin-right: 7px; + &.defaulticon.small { + background-color: @main_color_q; + border-radius:14px; + } + // square icons + &.icon-group { + .square-icon(); + background-color: @main_color_a; + + &::before { + content: "G"; + } + } + &.icon-policy { + .square-icon(); + background-color: @main_color_r; + + &::before { + content: "P"; + } + } + + } +} diff --git a/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.spec.ts b/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.spec.ts new file mode 100644 index 0000000000..e916d788ce --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.spec.ts @@ -0,0 +1,190 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import {NO_ERRORS_SCHEMA, SimpleChange} from '@angular/core'; +import {ComponentFixture} from '@angular/core/testing'; +import {ConfigureFn, configureTests} from '../../../../../jest/test-config.helper'; +import {ContentAfterLastDotPipe} from '../../../pipes/contentAfterLastDot.pipe'; +import {KeysPipe} from '../../../pipes/keys.pipe'; +import {SearchFilterPipe} from '../../../pipes/searchFilter.pipe'; +import {ModalService} from '../../../services/modal.service'; +import {AttributeRowSelectedEvent, AttributesTableComponent} from './attributes-table.component'; +import {AttributesService} from "../../../services/attributes.service"; +import {AttributeFEModel} from "../../../../models/attributes-outputs/attribute-fe-model"; +import {AttributeBEModel} from "app/models/attributes-outputs/attribute-be-model"; +import {DerivedFEAttribute} from "../../../../models/attributes-outputs/derived-fe-attribute"; +import {PropertiesOrderByPipe} from "app/ng2/pipes/properties-order-by.pipe"; + +describe('attributes-table component', () => { + + let fixture: ComponentFixture; + let attributesServiceMock: Partial; + let modalServiceMock: Partial; + + beforeEach( + () => { + attributesServiceMock = { + undoDisableRelatedAttributes: jest.fn(), + disableRelatedAttributes: jest.fn() + }; + modalServiceMock = {}; + + const configure: ConfigureFn = (testBed) => { + testBed.configureTestingModule({ + declarations: [ + AttributesTableComponent, + KeysPipe, + PropertiesOrderByPipe, + SearchFilterPipe, + ContentAfterLastDotPipe + ], + imports: [], + schemas: [NO_ERRORS_SCHEMA], + providers: [ + {provide: AttributesService, useValue: attributesServiceMock}, + {provide: ModalService, useValue: modalServiceMock} + ], + }); + }; + + configureTests(configure).then((testBed) => { + fixture = testBed.createComponent(AttributesTableComponent); + }); + } + ); + + it('When Properties assignment page is loaded, it is sorted by attribute name (acsending)', () => { + const fePropertiesMapValues = new SimpleChange('previousValue', 'currentValue', true); + const changes = { + fePropertiesMap: fePropertiesMapValues + }; + + // init values before ngOnChanges was called + fixture.componentInstance.sortBy = 'existingValue'; + + fixture.componentInstance.ngOnChanges(changes); + + expect(fixture.componentInstance.reverse).toEqual(true); + expect(fixture.componentInstance.direction).toEqual(fixture.componentInstance.ascUpperLettersFirst); + expect(fixture.componentInstance.sortBy).toEqual('name'); + expect(fixture.componentInstance.path.length).toEqual(1); + expect(fixture.componentInstance.path[0]).toEqual('name'); + }); + + it('When ngOnChanges is called without fePropertiesMap,' + + ' sortBy will remain as it was', () => { + const fePropertiesMapValues = new SimpleChange('previousValue', 'currentValue', true); + const changes = { + dummyKey: fePropertiesMapValues + }; + + // init values before ngOnChanges was called + fixture.componentInstance.sortBy = 'existingValue'; + fixture.componentInstance.sort = jest.fn(); + + fixture.componentInstance.ngOnChanges(changes); + + expect(fixture.componentInstance.sortBy).toEqual('existingValue'); + }); + + it('When sort is called init this.direction to 1', () => { + // init values + fixture.componentInstance.reverse = false; + fixture.componentInstance.direction = 0; + fixture.componentInstance.sortBy = 'initialize.Value'; + fixture.componentInstance.path = []; + + // call sore function + fixture.componentInstance.sort('initialize.Value'); + + // expect that + expect(fixture.componentInstance.reverse).toBe(true); + expect(fixture.componentInstance.direction).toBe(fixture.componentInstance.ascUpperLettersFirst); + expect(fixture.componentInstance.sortBy).toBe('initialize.Value'); + expect(fixture.componentInstance.path.length).toBe(2); + expect(fixture.componentInstance.path[0]).toBe('initialize'); + expect(fixture.componentInstance.path[1]).toBe('Value'); + }); + + it('When sort is called init this.direction to -1', () => { + // init values + fixture.componentInstance.reverse = true; + fixture.componentInstance.direction = 0; + fixture.componentInstance.sortBy = 'initialize.Value'; + fixture.componentInstance.path = []; + + // call sore function + fixture.componentInstance.sort('initialize.Value'); + + // expect that + expect(fixture.componentInstance.reverse).toBe(false); + expect(fixture.componentInstance.direction).toBe(fixture.componentInstance.descLowerLettersFirst); + }); + + it('When onPropertyChanged is called, event is emitted', () => { + spyOn(fixture.componentInstance.emitter, 'emit'); + fixture.componentInstance.onAttributeChanged('testProperty'); + expect(fixture.componentInstance.emitter.emit).toHaveBeenCalledWith('testProperty'); + }); + + it('When onClickPropertyRow is called, selectedPropertyId is updated and event is emitted.', () => { + const attributeFEModel = new AttributeFEModel(new AttributeBEModel()); + attributeFEModel.name = 'attributeName'; + const attributeRowSelectedEvent: AttributeRowSelectedEvent = new AttributeRowSelectedEvent(attributeFEModel, 'instanceName'); + + spyOn(fixture.componentInstance.selectAttributeRow, 'emit'); + fixture.componentInstance.onClickAttributeRow(attributeFEModel, 'instanceName'); + + expect(fixture.componentInstance.selectedAttributeId).toBe('attributeName'); + expect(fixture.componentInstance.selectAttributeRow.emit).toHaveBeenCalledWith(attributeRowSelectedEvent); + }); + + it('When onClickPropertyInnerRow is called, event is emitted.', () => { + const derivedFEProperty = new DerivedFEAttribute(new AttributeBEModel()); + const attributeRowSelectedEvent: AttributeRowSelectedEvent = new AttributeRowSelectedEvent(derivedFEProperty, 'instanceName'); + spyOn(fixture.componentInstance.selectAttributeRow, 'emit'); + fixture.componentInstance.onClickAttributeInnerRow(derivedFEProperty, 'instanceName'); + + expect(fixture.componentInstance.selectAttributeRow.emit).toHaveBeenCalledWith(attributeRowSelectedEvent); + }); + + it('When attributeChecked is called, attributesService.undoDisableRelatedProperties is called and event is emitted.', () => { + + const attributeFEModel = new AttributeFEModel(new AttributeBEModel()); + attributeFEModel.isSelected = false; + + spyOn(fixture.componentInstance.updateCheckedAttributeCount, 'emit'); + fixture.componentInstance.attributeChecked(attributeFEModel); + expect(attributesServiceMock.undoDisableRelatedAttributes).toHaveBeenCalledWith(attributeFEModel, undefined); + expect(fixture.componentInstance.updateCheckedAttributeCount.emit).toHaveBeenCalledWith(false); + }); + + it('When attributeChecked is called, attributesService.disableRelatedProperties is called and event is emitted.', () => { + + const attributeFEModel = new AttributeFEModel(new AttributeBEModel()); + attributeFEModel.isSelected = true; + + spyOn(fixture.componentInstance.updateCheckedAttributeCount, 'emit'); + fixture.componentInstance.attributeChecked(attributeFEModel); + expect(attributesServiceMock.disableRelatedAttributes).toHaveBeenCalledWith(attributeFEModel, undefined); + expect(fixture.componentInstance.updateCheckedAttributeCount.emit).toHaveBeenCalledWith(true); + }); + +}); diff --git a/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.ts b/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.ts new file mode 100644 index 0000000000..000e2cc6e9 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/attributes-table/attributes-table.component.ts @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core'; +import {InstanceFeDetails} from '../../../../models/instance-fe-details'; +import {InstanceFeAttributesMap} from "../../../../models/attributes-outputs/attribute-fe-map"; +import {AttributeFEModel} from "../../../../models/attributes-outputs/attribute-fe-model"; +import {AttributesService} from "../../../services/attributes.service"; +import {DerivedFEAttribute} from "../../../../models/attributes-outputs/derived-fe-attribute"; + +@Component({ + selector: 'attributes-table', + templateUrl: './attributes-table.component.html', + styleUrls: ['./attributes-table.component.less'] +}) +export class AttributesTableComponent implements OnChanges { + + @Input() feAttributesMap: InstanceFeAttributesMap; + @Input() feInstanceNamesMap: Map; + @Input() selectedAttributeId: string; + @Input() attributeNameSearchText: string; + @Input() searchTerm: string; + @Input() readonly: boolean; + @Input() isLoading: boolean; + @Input() hasDeclareOption: boolean; + @Input() hideAttributeType: boolean; + @Input() showDelete: boolean; + + @Output('attributeChanged') emitter: EventEmitter = new EventEmitter(); + @Output() selectAttributeRow: EventEmitter = new EventEmitter(); + @Output() updateCheckedAttributeCount: EventEmitter = new EventEmitter(); // only for hasDeclareOption + @Output() updateCheckedChildAttributeCount: EventEmitter = new EventEmitter();//only for hasDeclareListOption + @Output() deleteAttribute: EventEmitter = new EventEmitter(); + + sortBy: string; + reverse: boolean; + direction: number; + path: string[]; + + readonly ascUpperLettersFirst = 1; + readonly descLowerLettersFirst = -1; + + constructor(private attributesService: AttributesService) { + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes.fePropertiesMap) { + this.sortBy = ''; + this.sort('name'); + } + } + + sort(sortBy) { + this.reverse = (this.sortBy === sortBy) ? !this.reverse : true; + this.direction = this.reverse ? this.ascUpperLettersFirst : this.descLowerLettersFirst; + this.sortBy = sortBy; + this.path = sortBy.split('.'); + } + + onAttributeChanged = (attribute) => { + this.emitter.emit(attribute); + } + + // Click on main row (row of AttributeFEModel) + onClickAttributeRow = (attribute: AttributeFEModel, instanceName: string) => { + this.selectedAttributeId = attribute.name; + const attributeRowSelectedEvent: AttributeRowSelectedEvent = new AttributeRowSelectedEvent(attribute, instanceName); + this.selectAttributeRow.emit(attributeRowSelectedEvent); + } + + // Click on inner row (row of DerivedFEAttribute) + onClickAttributeInnerRow = (attribute: DerivedFEAttribute, instanceName: string) => { + const attributeRowSelectedEvent: AttributeRowSelectedEvent = new AttributeRowSelectedEvent(attribute, instanceName); + this.selectAttributeRow.emit(attributeRowSelectedEvent); + } + + attributeChecked = (attrib: AttributeFEModel, childAttribName?: string) => { + const isChecked: boolean = (!childAttribName) ? attrib.isSelected : attrib.flattenedChildren.find((attrib) => attrib.attributesName == childAttribName).isSelected; + + if (isChecked) { + this.attributesService.disableRelatedAttributes(attrib, childAttribName); + } else { + this.attributesService.undoDisableRelatedAttributes(attrib, childAttribName); + } + this.updateCheckedAttributeCount.emit(isChecked); + + } + +} + +export class AttributeRowSelectedEvent { + attributeModel: AttributeFEModel | DerivedFEAttribute; + instanceName: string; + + constructor(attributeModel: AttributeFEModel | DerivedFEAttribute, instanceName: string) { + this.attributeModel = attributeModel; + this.instanceName = instanceName; + } +} diff --git a/catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.html b/catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.html new file mode 100644 index 0000000000..7f271af4e1 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.html @@ -0,0 +1,102 @@ + + +
+ + +
+ +
{{attribute.name}}
+
+
+
{{attribute.name}}
+
+
+ +
+
+ + +
+ +
+
+ +
{{attribute.type | contentAfterLastDot }}
+
{{attribute.schema.property.type | contentAfterLastDot }}
+
+ +
+
+ + + Add value to list + + + + +
+ +
+ + + + +
diff --git a/catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.less b/catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.less new file mode 100644 index 0000000000..fd572b0f2d --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.less @@ -0,0 +1,82 @@ +@import '../../../../../../assets/styles/variables.less'; +.flat-children-container { + .dynamic-property-row { + /*create nested left border classes for up to 10 levels of nesting*/ + .nested-border-loop(@i) when (@i > 0) { + @size: (@i - 1) *2; + &.nested-level-@{i} .table-cell:first-child { + border-left: ~"solid @{size}px #009fdb"; + } + .nested-border-loop(@i - 1) + } + .nested-border-loop(10); + } + dynamic-property { + &:first-child .dynamic-property-row.with-top-border { + border-top:solid 1px #d2d2d2; + } + &:not(:last-child) .dynamic-property-row { + border-bottom:solid 1px #d2d2d2; + } + } +} +.dynamic-property-row { + display:flex; + flex-direction:row; + align-items: stretch; + + &.readonly{ + background-color: @tlv_color_t; + cursor: auto; + } + //for the case that the parent is disabled but the child is enabled + &:not(.readonly){ + background-color: @main_color_p; + } + + .table-cell { + flex: 1; + padding:9px; + justify-content: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + &:first-child { + flex: 0 0 50%; + border-right:#d2d2d2 solid 1px; + &:only-of-type { + flex: 1 1 100%; + border-right:none; + } + } + &.empty { + height:40px; + } + } + .property-icon { + flex: 0 0 auto; + margin-right:10px; + align-self:center; + cursor:pointer; + } +} + +.filtered { + /deep/ .checkbox-label-content{ + background-color: yellow; + } +} +.inner-cell-div{ + max-width: 100%; + text-overflow: ellipsis; + overflow: hidden; + display: inline; + padding-left: 8px; +} +.error { + border: solid 1px @func_color_q; + color: @func_color_q; + outline: none; + box-sizing: border-box; +} diff --git a/catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.ts b/catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.ts new file mode 100644 index 0000000000..39faac9283 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/attributes-table/dynamic-attribute/dynamic-attribute.component.ts @@ -0,0 +1,232 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import * as _ from "lodash"; +import {Component, EventEmitter, Input, Output, ViewChild} from "@angular/core"; +import {PROPERTY_TYPES} from 'app/utils'; +import {DataTypeService} from "../../../../services/data-type.service"; +import {animate, style, transition, trigger} from '@angular/animations'; +import {IUiElementChangeEvent} from "../../../ui/form-components/ui-element-base.component"; +import {DynamicElementComponent} from "../../../ui/dynamic-element/dynamic-element.component"; +import {DerivedAttributeType} from "../../../../../models/attributes-outputs/attribute-be-model"; +import {AttributeFEModel} from "app/models/attributes-outputs/attribute-fe-model"; +import {DerivedFEAttribute} from "../../../../../models/attributes-outputs/derived-fe-attribute"; +import {AttributesUtils} from "../../../../pages/attributes-outputs/services/attributes.utils"; + +@Component({ + selector: 'dynamic-property', + templateUrl: './dynamic-attribute.component.html', + styleUrls: ['./dynamic-attribute.component.less'], + animations: [trigger('fadeIn', [transition(':enter', [style({opacity: '0'}), animate('.7s ease-out', style({opacity: '1'}))])])] +}) +export class DynamicAttributeComponent { + + derivedAttributeType = DerivedAttributeType; + attribType: DerivedAttributeType; + attribPath: string; + isAttributeFEModel: boolean; + nestedLevel: number; + attributeTestsId: string; + constraints: string[]; + + @Input() canBeDeclared: boolean; + @Input() attribute: AttributeFEModel | DerivedFEAttribute; + @Input() expandedChildId: string; + @Input() selectedAttributeId: string; + @Input() attributeNameSearchText: string; + @Input() readonly: boolean; + @Input() hasChildren: boolean; + @Input() hasDeclareOption: boolean; + @Input() rootAttribute: AttributeFEModel; + + @Output('attributeChanged') emitter: EventEmitter = new EventEmitter(); + @Output() expandChild: EventEmitter = new EventEmitter(); + @Output() checkAttribute: EventEmitter = new EventEmitter(); + @Output() deleteItem: EventEmitter = new EventEmitter(); + @Output() clickOnAttributeRow: EventEmitter = new EventEmitter(); + @Output() mapKeyChanged: EventEmitter = new EventEmitter(); + @Output() addChildAttribsToParent: EventEmitter> = new EventEmitter>(); + + @ViewChild('mapKeyInput') public mapKeyInput: DynamicElementComponent; + + constructor(private attributesUtils: AttributesUtils, private dataTypeService: DataTypeService) { + } + + ngOnInit() { + this.isAttributeFEModel = this.attribute instanceof AttributeFEModel; + this.attribType = this.attribute.derivedDataType; + this.attribPath = (this.attribute instanceof AttributeFEModel) ? this.attribute.name : this.attribute.attributesName; + this.nestedLevel = (this.attribute.attributesName.match(/#/g) || []).length; + this.rootAttribute = (this.rootAttribute) ? this.rootAttribute : this.attribute; + this.attributeTestsId = this.getAttributeTestsId(); + + this.initConstraintsValues(); + + } + + initConstraintsValues() { + let primitiveProperties = ['string', 'integer', 'float', 'boolean']; + + if (this.attribute.constraints) { + this.constraints = this.attribute.constraints[0].validValues + } + + //Complex Type + else if (primitiveProperties.indexOf(this.rootAttribute.type) == -1 && primitiveProperties.indexOf(this.attribute.type) >= 0) { + this.constraints = this.dataTypeService.getConstraintsByParentTypeAndUniqueID(this.rootAttribute.type, this.attribute.name); + } else { + this.constraints = null; + } + + } + + onClickPropertyRow = (property, event) => { + // Because DynamicAttributeComponent is recursive second time the event is fire event.stopPropagation = undefined + event && event.stopPropagation && event.stopPropagation(); + this.clickOnAttributeRow.emit(property); + } + + expandChildById = (id: string) => { + this.expandedChildId = id; + this.expandChild.emit(id); + } + + checkedChange = (propName: string) => { + this.checkAttribute.emit(propName); + } + + getHasChildren = (property: DerivedFEAttribute): boolean => {// enter to this function only from base property (AttributeFEModel) and check for child property if it has children + return _.filter((this.attribute).flattenedChildren, (prop: DerivedFEAttribute) => { + return _.startsWith(prop.attributesName + '#', property.attributesName); + }).length > 1; + } + + getAttributeTestsId = () => { + return [this.rootAttribute.name].concat(this.rootAttribute.getParentNamesArray(this.attribute.attributesName, [], true)).join('.'); + }; + + onElementChanged = (event: IUiElementChangeEvent) => { + this.attribute.updateValueObj(event.value, event.isValid); + this.emitter.emit(); + }; + + createNewChildProperty = (): void => { + + let newProps: Array = this.attributesUtils.createListOrMapChildren(this.attribute, "", null); + this.attributesUtils.assignFlattenedChildrenValues(this.attribute.valueObj, [newProps[0]], this.attribute.attributesName); + if (this.attribute instanceof AttributeFEModel) { + this.addChildProps(newProps, this.attribute.name); + } else { + this.addChildAttribsToParent.emit(newProps); + } + } + + addChildProps = (newProps: Array, childPropName: string) => { + + if (this.attribute instanceof AttributeFEModel) { + let insertIndex: number = this.attribute.getIndexOfChild(childPropName) + this.attribute.getCountOfChildren(childPropName); //insert after parent prop and existing children + this.attribute.flattenedChildren.splice(insertIndex, 0, ...newProps); //using ES6 spread operator + this.expandChildById(newProps[0].attributesName); + + this.updateMapKeyValueOnMainParent(newProps); + this.emitter.emit(); + } + } + + updateMapKeyValueOnMainParent(childrenProps: Array) { + if (this.attribute instanceof AttributeFEModel) { + const attributeFEModel: AttributeFEModel = this.attribute; + //Update only if all this attributeFEModel parents has key name + if (attributeFEModel.getParentNamesArray(childrenProps[0].attributesName, []).indexOf('') === -1) { + angular.forEach(childrenProps, (prop: DerivedFEAttribute): void => { //Update parent AttributeFEModel with value for each child, including nested props + attributeFEModel.childPropUpdated(prop); + if (prop.isChildOfListOrMap && prop.mapKey !== undefined) { + attributeFEModel.childPropMapKeyUpdated(prop, prop.mapKey, true); + } + }, this); + //grab the cumulative value for the new item from parent AttributeFEModel and assign that value to DerivedFEProp[0] (which is the list or map parent with UUID of the set we just added) + let parentNames = (attributeFEModel).getParentNamesArray(childrenProps[0].attributesName, []); + childrenProps[0].valueObj = _.get(attributeFEModel.valueObj, parentNames.join('.'), null); + } + } + } + + childValueChanged = (property: DerivedFEAttribute) => { //value of child property changed + + if (this.attribute instanceof AttributeFEModel) { // will always be the case + if (this.attribute.getParentNamesArray(property.attributesName, []).indexOf('') === -1) {//If one of the parents is empty key -don't save + this.attribute.childPropUpdated(property); + this.emitter.emit(); + } + } + } + + deleteListOrMapItem = (item: DerivedFEAttribute) => { + if (this.attribute instanceof AttributeFEModel) { + this.removeValueFromParent(item); + this.attribute.flattenedChildren.splice(this.attribute.getIndexOfChild(item.attributesName), this.attribute.getCountOfChildren(item.attributesName)); + this.expandChildById(item.attributesName); + } + } + + removeValueFromParent = (item: DerivedFEAttribute) => { + if (this.attribute instanceof AttributeFEModel) { + let itemParent = (item.parentName == this.attribute.name) + ? this.attribute : this.attribute.flattenedChildren.find(prop => prop.attributesName == item.parentName); + if (!itemParent) { + return; + } + + if (item.derivedDataType == DerivedAttributeType.MAP) { + const oldKey = item.getActualMapKey(); + delete itemParent.valueObj[oldKey]; + if (itemParent instanceof AttributeFEModel) { + delete itemParent.valueObjValidation[oldKey]; + itemParent.valueObjIsValid = itemParent.calculateValueObjIsValid(); + } + this.attribute.childPropMapKeyUpdated(item, null); // remove map key + } else { + const itemIndex: number = this.attribute.flattenedChildren.filter(prop => prop.parentName == item.parentName).map(prop => prop.attributesName).indexOf(item.attributesName); + itemParent.valueObj.splice(itemIndex, 1); + if (itemParent instanceof AttributeFEModel) { + itemParent.valueObjValidation.splice(itemIndex, 1); + itemParent.valueObjIsValid = itemParent.calculateValueObjIsValid(); + } + } + if (itemParent instanceof AttributeFEModel) { //direct child + this.emitter.emit(); + } else { //nested child - need to update parent prop by getting flattened name (recurse through parents and replace map/list keys, etc) + this.childValueChanged(itemParent); + } + } + } + + updateChildKeyInParent(childProp: DerivedFEAttribute, newMapKey: string) { + if (this.attribute instanceof AttributeFEModel) { + this.attribute.childPropMapKeyUpdated(childProp, newMapKey); + this.emitter.emit(); + } + } + + preventInsertItem = (property: DerivedFEAttribute): boolean => { + return property.type == PROPERTY_TYPES.MAP && Object.keys(property.valueObj).indexOf('') > -1; + } + +} diff --git a/catalog-ui/src/app/ng2/components/logic/attributes-table/pipes/filterChildAttributes.pipe.ts b/catalog-ui/src/app/ng2/components/logic/attributes-table/pipes/filterChildAttributes.pipe.ts new file mode 100644 index 0000000000..b2098d8478 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/attributes-table/pipes/filterChildAttributes.pipe.ts @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import {Pipe, PipeTransform} from '@angular/core'; +import {DerivedFEAttribute} from "../../../../../models/attributes-outputs/derived-fe-attribute"; + +@Pipe({ + name: 'filterChildAttributes', +}) +export class FilterChildAttributesPipe implements PipeTransform { + public transform(childAttributes: Array, parentId: string) { + if (!parentId || !childAttributes) return childAttributes; + + let validParents: Array = [parentId]; + while (parentId.lastIndexOf('#') > 0) { + parentId = parentId.substring(0, parentId.lastIndexOf('#')); + validParents.push(parentId); + } + return childAttributes.filter(derivedAttrib => validParents.indexOf(derivedAttrib.parentName) > -1); + } +} diff --git a/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.module.ts b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.module.ts new file mode 100644 index 0000000000..fc6c73f2f6 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.module.ts @@ -0,0 +1,32 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import {NgModule} from '@angular/core' +import {BrowserModule} from '@angular/platform-browser' +import {HierarchyNavigationComponent} from "./hierarchy-navigation.component"; + +@NgModule({ + imports: [BrowserModule], + declarations: [HierarchyNavigationComponent], + bootstrap: [], + exports: [HierarchyNavigationComponent] +}) +export class HierarchyNavigationModule { +} 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 @@ + + +
+ +
+
Output Name + +
+
From + Instance + +
+
Type + + +
+
+ Req. in RT +
+
Value
+
+
+
No data to display
+
+
+ +
+
+ {{output.name}} +
+ +
+ +
+
+ {{instanceNamesMap[output.instanceUniqueId]?.name}} +
+
+ +
+
+ {{output.type | contentAfterLastDot}} +
+
+ +
+ +
+ +
+ + +
+ +
+
+
+
+
+
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; + @Input() instanceNamesMap: Map; + @Input() readonly: boolean; + @Input() isLoading: boolean; + @Input() componentType: string; + @Output() outputChanged: EventEmitter = new EventEmitter(); + @Output() deleteOutput: EventEmitter = new EventEmitter(); + @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 + } + +} diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts index e499b3786b..b79bec0942 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts @@ -81,7 +81,6 @@ export class PropertiesTableComponent implements OnChanges { // Click on main row (row of propertyFEModel) onClickPropertyRow = (property: PropertyFEModel, instanceName: string, event?) => { - // event && event.stopPropagation(); this.selectedPropertyId = property.name; const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName); this.selectPropertyRow.emit(propertyRowSelectedEvent); -- cgit 1.2.3-korg