From aa72781388f3e6408bb43f1b024d88ec1c9d2c10 Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Tue, 4 Oct 2022 20:29:28 +0100 Subject: Add data type properties workspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the properties workspace for a data type, with the list and filter feature. Change-Id: I2ec337a0481bddd5fe32e45644abdc88e197fa49 Issue-ID: SDC-4214 Signed-off-by: André Schmid --- .../type-workspace-properties.component.html | 62 +++++++++ .../type-workspace-properties.component.less | 141 +++++++++++++++++++++ .../type-workspace-properties.component.spec.ts | 111 ++++++++++++++++ .../type-workspace-properties.component.ts | 115 +++++++++++++++++ .../type-workspace/type-workspace.component.html | 6 +- .../type-workspace.component.spec.ts | 6 +- .../pages/type-workspace/type-workspace.module.ts | 7 +- 7 files changed, 442 insertions(+), 6 deletions(-) create mode 100644 catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html create mode 100644 catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.less create mode 100644 catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.spec.ts create mode 100644 catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts (limited to 'catalog-ui/src/app/ng2/pages') diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html new file mode 100644 index 0000000000..61c319eb6f --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html @@ -0,0 +1,62 @@ + + +
+
+ {{'PROPERTY_SHOWING_LABEL' | translate}}: {{filteredProperties.length}} of {{properties.length}} + + +
+
+
+
+
{{header.title}} + +
+
+
+ +
+
+ {{'PROPERTY_LIST_EMPTY_MESSAGE' | translate}} +
+
+ + +
+ {{property.type}} +
+
+ {{property.getSchemaType() || ''}} +
+
+ {{property.description}} +
+
+
+
+ +
+
+ +
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.less b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.less new file mode 100644 index 0000000000..9c101e8ce3 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.less @@ -0,0 +1,141 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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========================================================= + */ + +@import "../../../../../assets/styles/sprite-old"; +@import "../../../../../assets/styles/mixins_old"; + +.workspace-properties { + + width: 93%; + display: inline-block; + + #left-top-bar { + float: left; + width: 186px; + + ::-webkit-input-placeholder { + font-style: italic; + } + + :-moz-placeholder { + font-style: italic; + } + + ::-moz-placeholder { + font-style: italic; + } + + :-ms-input-placeholder { + font-style: italic; + } + + #properties-count { + font-weight: bold; + float: left; + } + + #search-by-name { + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + width: 270px; + height: 32px; + line-height: 32px; + border: 1px solid @main_color_o; + text-indent: 10px; + } + + .search-button { + .hand; + cursor: pointer; + float: right; + position: relative; + top: -22px; + right: -80px; + } + } + + .delete-col-header { + .sprite(); + .sprite.e-sdc-small-icon-delete(); + } + + .table { + height: 100%; + min-height: 500px; + margin-bottom: 0; + } + + .data-row { + .table-delete-btn { + display: none !important; + } + + &:hover { + .table-delete-btn { + display: inline-block !important; + } + } + } + + .table-container-flex { + margin-top: 0; + overflow: scroll; + &::-webkit-scrollbar-track { + border: 0; + } + + .text { + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + white-space: nowrap; + } + + .flex-item:nth-child(1) { + flex-grow: 15; + + a { + .hand + } + } + + .flex-item:nth-child(2) { + flex-grow: 6; + } + + .flex-item:nth-child(3) { + flex-grow: 6; + } + + .flex-item:nth-child(4) { + flex-grow: 20; + white-space: normal; + } + + .flex-item:nth-child(5) { + flex-grow: 3; + padding-top: 10px; + } + + } + +} diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.spec.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.spec.ts new file mode 100644 index 0000000000..6be572d16a --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.spec.ts @@ -0,0 +1,111 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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========================================================= + */ + +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; + +import {TypeWorkspacePropertiesComponent} from './type-workspace-properties.component'; +import {FormsModule} from "@angular/forms"; +import {TranslateModule} from "../../../shared/translator/translate.module"; +import {TranslateService} from "../../../shared/translator/translate.service"; +import {DataTypeService} from "../../../services/data-type.service"; +import {Observable} from "rxjs/Observable"; +import {DataTypeModel} from "../../../../models/data-types"; +import {Component, ViewChild} from "@angular/core"; +import {PropertyBEModel} from "../../../../models/properties-inputs/property-be-model"; + +describe('TypeWorkspacePropertiesComponent', () => { + const messages = require("../../../../../assets/languages/en_US.json"); + let testHostComponent: TestHostComponent; + let testHostFixture: ComponentFixture; + let dataTypeServiceMock: Partial = { + findAllProperties: jest.fn( (dataTypeId) => { + if (dataTypeId === 'dataTypeId') { + const property1 = new PropertyBEModel(); + property1.name = 'property1' + property1.type = 'string' + return Observable.of([property1]); + } + return Observable.of([]); + }) + }; + + let translateServiceMock: Partial = { + 'translate': jest.fn( (translateKey: string) => { + return messages[translateKey]; + }) + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [TypeWorkspacePropertiesComponent, TestHostComponent], + imports: [ + TranslateModule, + FormsModule + ], + providers: [ + {provide: DataTypeService, useValue: dataTypeServiceMock}, + {provide: TranslateService, useValue: translateServiceMock} + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + testHostFixture = TestBed.createComponent(TestHostComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + }); + + it('should create', () => { + expect(testHostComponent).toBeTruthy(); + }); + + it('empty property list', () => { + const element = testHostFixture.nativeElement; + const div: HTMLDivElement = element.querySelector('.no-row-text'); + expect(div.textContent).toContain(messages.PROPERTY_LIST_EMPTY_MESSAGE); + }); + + it('test property list', () => { + testHostFixture = TestBed.createComponent(TestHostComponent); + testHostComponent = testHostFixture.componentInstance; + const dataType = new DataTypeModel(); + dataType.uniqueId = 'dataTypeId'; + testHostComponent.typeWorkspacePropertiesComponent.dataType = dataType; + testHostFixture.detectChanges(); + + const element = testHostFixture.nativeElement; + expect(element.querySelector('.no-row-text')).toBeFalsy(); + const expectedPropertyName = 'property1'; + const propertyNameLink: HTMLAnchorElement = element.querySelector(`a[data-tests-id^="property-name-${expectedPropertyName}"]`); + expect(propertyNameLink.textContent).toContain(expectedPropertyName); + }); + + @Component({ + selector: 'host-component', + template: `` + }) + class TestHostComponent { + @ViewChild(TypeWorkspacePropertiesComponent) + public typeWorkspacePropertiesComponent: TypeWorkspacePropertiesComponent; + } + +}); diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts new file mode 100644 index 0000000000..931fd3d97c --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts @@ -0,0 +1,115 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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========================================================= + */ + +import {Component, Input, OnInit} from '@angular/core'; +import {DataTypeModel} from "../../../../models/data-types"; +import {DataTypeService} from "../../../services/data-type.service"; +import {PropertyBEModel} from "../../../../models/properties-inputs/property-be-model"; +import { Subject } from "rxjs"; +import {debounceTime, distinctUntilChanged} from "rxjs/operators"; + +@Component({ + selector: 'app-type-workspace-properties', + templateUrl: './type-workspace-properties.component.html', + styleUrls: ['./type-workspace-properties.component.less'] +}) +export class TypeWorkspacePropertiesComponent implements OnInit { + @Input() isViewOnly = true; + @Input() dataType: DataTypeModel = new DataTypeModel(); + + properties: Array = []; + filteredProperties: Array = []; + tableHeadersList: Array = []; + tableSortBy: string = 'name'; + tableColumnReverse: boolean = false; + tableFilterTerm: string = undefined; + tableSearchTermUpdate = new Subject(); + + constructor(private dataTypeService: DataTypeService) { } + + ngOnInit(): void { + this.initTable(); + this.initProperties(); + this.tableSearchTermUpdate.pipe( + debounceTime(400), + distinctUntilChanged()) + .subscribe(searchTerm => { + this.filter(searchTerm); + }); + } + + private initTable(): void { + this.tableHeadersList = [ + {title: 'Name', property: 'name'}, + {title: 'Type', property: 'type'}, + {title: 'Schema', property: 'schema.property.type'}, + {title: 'Description', property: 'description'}, + ]; + + this.tableSortBy = this.tableHeadersList[0].property; + } + + private initProperties(): void { + this.dataTypeService.findAllProperties(this.dataType.uniqueId).subscribe(properties => { + this.properties = properties.map(value => new PropertyBEModel(value)); + this.filteredProperties = Array.from(this.properties); + this.sort(); + }); + } + + onUpdateSort(property: string): void { + if (this.tableSortBy === property) { + this.tableColumnReverse = !this.tableColumnReverse; + } else { + this.tableColumnReverse = false; + this.tableSortBy = property; + } + this.sort(); + } + + private sort(): void { + const field = this.tableSortBy; + this.filteredProperties = this.filteredProperties.sort((property1, property2) => { + const result = property1[field] > property2[field] ? 1 : property1[field] < property2[field] ? -1 : 0; + return this.tableColumnReverse ? result * -1 : result; + }); + } + + private filter(searchTerm: string): void { + if (searchTerm) { + searchTerm = searchTerm.toLowerCase(); + this.filteredProperties = this.properties.filter(property => + property.name.toLowerCase().includes(searchTerm) + || property.type.toLowerCase().includes(searchTerm) + || (property.getSchemaType() && property.getSchemaType().toLowerCase().includes(searchTerm)) + || (property.description && property.description.toLowerCase().includes(searchTerm)) + ); + } else { + this.filteredProperties = Array.from(this.properties); + } + this.sort(); + } +} + +interface TableHeader { + title: string; + property: string; +} \ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html index 8d6ae02598..193c94e6ad 100644 --- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html @@ -42,9 +42,11 @@ {{currentMenu.text}} -
- +
+ +
+
diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts index 8450da829b..fcad472890 100644 --- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts @@ -22,7 +22,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {TypeWorkspaceComponent} from './type-workspace.component'; -import {ReactiveFormsModule} from "@angular/forms"; +import {FormsModule, ReactiveFormsModule} from "@angular/forms"; import {TranslateModule} from "../../shared/translator/translate.module"; import {UiElementsModule} from "../../components/ui/ui-elements.module"; import {DataTypeService} from "../../services/data-type.service"; @@ -37,6 +37,7 @@ import {ISdcConfig, SdcConfigToken} from "../../config/sdc-config.config"; import {States} from "../../../utils/constants"; import {IUserProperties} from "../../../models/user"; import {Observable} from "rxjs/Observable"; +import {TypeWorkspacePropertiesComponent} from "./type-workspace-properties/type-workspace-properties.component"; describe('TypeWorkspaceComponent', () => { let component: TypeWorkspaceComponent; @@ -88,9 +89,10 @@ describe('TypeWorkspaceComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ TypeWorkspaceComponent, WorkspaceMenuComponent, TypeWorkspaceGeneralComponent ], + declarations: [ TypeWorkspaceComponent, WorkspaceMenuComponent, TypeWorkspaceGeneralComponent, TypeWorkspacePropertiesComponent ], imports: [ ReactiveFormsModule, + FormsModule, TranslateModule, UiElementsModule, LayoutModule diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts index d3f391db24..021f84af09 100644 --- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts @@ -28,9 +28,10 @@ import {UiElementsModule} from "../../components/ui/ui-elements.module"; import {LayoutModule} from "../../components/layout/layout.module"; import {TypeWorkspaceGeneralComponent} from './type-workspace-general/type-workspace-general.component'; import {UpgradeModule} from "@angular/upgrade/static"; -import {ReactiveFormsModule} from "@angular/forms"; +import {FormsModule, ReactiveFormsModule} from "@angular/forms"; import {TranslateModule} from "../../shared/translator/translate.module"; import {DataTypeService} from "../../services/data-type.service"; +import { TypeWorkspacePropertiesComponent } from './type-workspace-properties/type-workspace-properties.component'; @NgModule({ imports: [ @@ -40,11 +41,13 @@ import {DataTypeService} from "../../services/data-type.service"; UpgradeModule, ReactiveFormsModule, TranslateModule, + FormsModule, ], declarations: [ TypeWorkspaceComponent, WorkspaceMenuComponent, - TypeWorkspaceGeneralComponent + TypeWorkspaceGeneralComponent, + TypeWorkspacePropertiesComponent ], providers: [ CacheService, -- cgit 1.2.3-korg