diff options
author | andre.schmid <andre.schmid@est.tech> | 2022-09-23 12:31:12 +0100 |
---|---|---|
committer | Michael Morris <michael.morris@est.tech> | 2022-10-05 08:18:25 +0000 |
commit | 6ed5592ccb3b2bdb61403f1d1d41d93088cb0709 (patch) | |
tree | 1978737dc736d000dbb34a9ddc50a7e2008ab573 /catalog-ui/src/app/ng2 | |
parent | 404bfc9c50e95df1e75dbf8325fae41bfd96871a (diff) |
Add data type view/workspace
Implements a data type workspace, based on the Service/VF workspace,
where it is possible to view a data type information.
Issue-ID: SDC-4193
Signed-off-by: André Schmid <andre.schmid@est.tech>
Change-Id: Ica341efa43e70b4ac85d42d22a1397e0ab6e2794
Diffstat (limited to 'catalog-ui/src/app/ng2')
19 files changed, 1033 insertions, 34 deletions
diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts index 7153f0a841..801b663d69 100644 --- a/catalog-ui/src/app/ng2/app.module.ts +++ b/catalog-ui/src/app/ng2/app.module.ts @@ -108,6 +108,7 @@ import {ElementService} from "./services/element.service"; import {ModelService} from "./services/model.service"; import {ToscaArtifactService} from "./services/tosca-artifact.service"; import {InterfaceDefinitionModule} from "./pages/interface-definition/interface-definition.module"; +import {TypeWorkspaceModule} from "./pages/type-workspace/type-workspace.module"; declare const __ENV__: string; @@ -172,6 +173,7 @@ export function configServiceFactory(config: ConfigService, authService: Authent ServiceDependenciesModule, ServiceDependenciesEditorModule, WorkspaceModule, + TypeWorkspaceModule, ModalsModule, CatalogModule, HomeModule, diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts index 3bd2255488..2b7be9cdeb 100644 --- a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts @@ -19,17 +19,13 @@ */ import * as _ from "lodash"; -import {Component, Inject, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges} from "@angular/core"; -import {IHostedApplication, IUserProperties} from "app/models"; -import {MenuItemGroup, MenuItem} from "app/utils"; +import {Component, EventEmitter, Inject, Input, OnChanges, OnInit, Output} from "@angular/core"; +import {IHostedApplication, IUserProperties, Plugin, PluginsConfiguration} from "app/models"; +import {MenuItem, MenuItemGroup} from "app/utils"; import {AuthenticationService} from "../../../services/authentication.service"; -import {SdcConfigToken, ISdcConfig} from "../../../config/sdc-config.config"; +import {ISdcConfig, SdcConfigToken} from "../../../config/sdc-config.config"; import {TranslateService} from "../../../shared/translator/translate.service"; -import {PluginsConfiguration, Plugin} from "app/models"; -import { Subscription } from "rxjs"; -// import { Store } from "@ngrx/store"; -// import { AppState } from "app/ng2/store/app.state"; -// import * as unsavedChangesReducer from 'app/ng2/store/reducers/unsaved-changes.reducer'; +import {Subscription} from "rxjs"; declare const window:any; @Component({ @@ -111,13 +107,13 @@ export class TopNavComponent implements OnInit, OnChanges { ngOnChanges(changes) { if (changes['menuModel']) { - console.log('menuModel was changed!'); + console.debug('menuModel was changed!'); this.generateMenu(); } } ngOnInit() { - console.log('Nav is init!', this.menuModel); + console.debug('Nav is init!', this.menuModel); this.user = this.authService.getLoggedinUser(); this.topNavPlugins = _.filter(PluginsConfiguration.plugins, (plugin: Plugin) => { return plugin.pluginDisplayOptions["tab"] !== undefined; @@ -190,7 +186,7 @@ export class TopNavComponent implements OnInit, OnChanges { if (item.callback) { (item.callback.apply(undefined, item.params)).then(onSuccess, onFailed); - } else { + } else if (this[item.action]) { this[item.action](item.state, item.params).then(onSuccess, onFailed); } } diff --git a/catalog-ui/src/app/ng2/config/sdc-menu.config.factory.ts b/catalog-ui/src/app/ng2/config/sdc-menu.config.factory.ts index 0e2b93dd7c..d2dfc57843 100644 --- a/catalog-ui/src/app/ng2/config/sdc-menu.config.factory.ts +++ b/catalog-ui/src/app/ng2/config/sdc-menu.config.factory.ts @@ -13,10 +13,9 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. -- */ - + import {IAppMenu} from "app/models"; -export function getSdcMenu() : IAppMenu{ - const sdcMenu:IAppMenu = require('./../../../../configurations/menu.js'); - return sdcMenu; +export function getSdcMenu(): IAppMenu { + return require('./../../../../configurations/menu.js'); } diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.html new file mode 100644 index 0000000000..877c58bd58 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.html @@ -0,0 +1,79 @@ +<!-- + ~ - + ~ ============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========================================================= + --> + +<div class="sdc-workspace-general-step"> + <form class="w-sdc-form" [formGroup]="formGroup"> + <div class="w-sdc-form-section-container"> + <div class="w-sdc-form-columns-wrapper"> + <div class="w-sdc-form-column"> + <div class="upper-general-fields"> + <div class="name-and-category-fields"> + <div class="i-sdc-form-item" [ngClass]="{'error': false}"> + <label class="i-sdc-form-label" [ngClass]="{'required': !isViewOnly}">{{'TYPE_LABEL' | translate}}:</label> + <span>{{dataType.name}}</span> + </div> + + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label" [ngClass]="{'required': !isViewOnly}">{{'MODEL_LABEL' | translate}}:</label> + <span>{{dataType.model ? dataType.model : DEFAULT_MODEL_NAME}}</span> + </div> + + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label" [ngClass]="{'required': !isViewOnly}">{{'DERIVED_FROM_LABEL' | translate}}:</label> + <span>{{dataType.derivedFromName}}</span> + </div> + </div> + </div> + + <div class="i-sdc-form-item description-field"> + <label class="i-sdc-form-label" [ngClass]="{'required': !isViewOnly}">{{'DESCRIPTION_LABEL' | translate}}:</label> + <textarea class="description" + formControlName="description" + [ngClass]="{'view-mode': isViewOnly}" + [required]="true" + [attr.test-id]="description" + [value]="dataType.description"></textarea> + </div> + </div> + + <div class="w-sdc-form-column"> + <div class="meta-data" data-ng-if="component.creationDate"> + <div> + <strong>{{'CREATED_LABEL' | translate}}:</strong> + </div> + <div class="meta-data-item-value">{{dataType.creationTime | date:'MM/dd/yyyy'}}</div> + <div> + <strong>{{'MODIFIED_LABEL' | translate}}:</strong> + </div> + <div class="meta-data-item-value"> + {{dataType.modificationTime | date:'MM/dd/yyyy'}} + </div> + <div> + <strong>{{'UNIQUE_ID_LABEL' | translate}}:</strong> + </div> + <div class="meta-data-item-value">{{dataType.uniqueId}}</div> + </div> + </div> + + </div> + </div> + </form> +</div> diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.less b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.less new file mode 100644 index 0000000000..3d9e984809 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.less @@ -0,0 +1,20 @@ +/* + * - + * ============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========================================================= + */ diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.spec.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.spec.ts new file mode 100644 index 0000000000..fe7b070354 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.spec.ts @@ -0,0 +1,59 @@ +/* + * - + * ============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 {TypeWorkspaceGeneralComponent} from './type-workspace-general.component'; +import {ReactiveFormsModule} from "@angular/forms"; +import {TranslateModule} from "../../../shared/translator/translate.module"; +import {TranslateService} from "../../../shared/translator/translate.service"; + +describe('TypeWorkspaceGeneralComponent', () => { + let component: TypeWorkspaceGeneralComponent; + let fixture: ComponentFixture<TypeWorkspaceGeneralComponent>; + let translateServiceMock: Partial<TranslateService> = { + 'translate': jest.fn() + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TypeWorkspaceGeneralComponent ], + imports: [ + ReactiveFormsModule, + TranslateModule + ], + providers: [ + {provide: TranslateService, useValue: translateServiceMock} + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TypeWorkspaceGeneralComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.ts new file mode 100644 index 0000000000..8728c3020e --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component.ts @@ -0,0 +1,62 @@ +/* + * - + * ============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 {FormControl, FormGroup, Validators} from "@angular/forms"; +import {DataTypeModel} from "../../../../models/data-types"; +import { DEFAULT_MODEL_NAME } from "app/utils/constants"; + +@Component({ + selector: 'app-type-workspace-general', + templateUrl: './type-workspace-general.component.html', + styleUrls: ['./type-workspace-general.component.less'] +}) +export class TypeWorkspaceGeneralComponent implements OnInit { + @Input() isViewOnly = true; + @Input() dataType: DataTypeModel = new DataTypeModel(); + + DEFAULT_MODEL_NAME = DEFAULT_MODEL_NAME; + + type: FormControl = new FormControl(undefined, [Validators.required, Validators.minLength(1), Validators.maxLength(300)]); + derivedFrom: FormControl = new FormControl(undefined, [Validators.required, Validators.minLength(1)]); + description: FormControl = new FormControl(undefined, [Validators.required, Validators.minLength(1)]); + model: FormControl = new FormControl(undefined, [Validators.required]); + formGroup: FormGroup = new FormGroup({ + 'type': this.type, + 'description': this.description, + 'model': this.model, + 'derivedFrom': this.derivedFrom + }); + + ngOnInit(): void { + this.initForm(); + } + + private initForm(): void { + if (!this.dataType) { + return; + } + this.type.setValue(this.dataType.name); + this.description.setValue(this.dataType.description); + this.model.setValue(this.dataType.model); + this.derivedFrom.setValue(this.dataType.derivedFrom); + } +} 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 new file mode 100644 index 0000000000..8d6ae02598 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.html @@ -0,0 +1,53 @@ +<!-- + ~ - + ~ ============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========================================================= + --> + +<div class="sdc-workspace-container"> + <loader [display]="isLoading"></loader> + <div class="w-sdc-main-container"> + <app-workspace-menu [menuHeader]="dataType.name" + (onMenuUpdate)="onMenuUpdate($event)" + (onClick)="onMenuClick($event)"> + </app-workspace-menu> + + <div class="w-sdc-main-right-container"> + <div class="sdc-workspace-top-bar"> + <div class="progress-container"> + </div> + <div class="sdc-workspace-top-bar-buttons"> + <span class="sprite-new x-btn" (click)="goToBreadcrumbHome()" sdc-smart-tooltip="Close" [title]="'CLOSE_LABEL' | translate"></span> + </div> + </div> + + <div class="w-sdc-main-container-body-content-wrapper"> + <div class="w-sdc-main-container-body-content-header"> + <div class="workspace-tab-title"> + {{currentMenu.text}} + </div> + </div> + <div class="w-sdc-main-container-body-content"> + <app-type-workspace-general *ngIf="currentMenu.state === 'general' && dataType" [dataType]="dataType"></app-type-workspace-general> + </div> + </div> + + </div> + </div> + <top-nav [hideSearch]="true" [menuModel]="breadcrumbsModel" [version]="sdcVersion" [unsavedChanges]="false"></top-nav> +</div> diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.less b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.less new file mode 100644 index 0000000000..4839b24f5e --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.less @@ -0,0 +1,149 @@ +/* + * - + * ============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/variables.less'; +@import '../../../../assets/styles/mixins.less'; +@import '../../../../assets/styles/mixins_old.less'; +@import '../../../../assets/styles/sprite.less'; + +.sdc-workspace-container { + .bg_p; + + .w-sdc-main-right-container { + + padding: 0; + background-color: @main_color_p; + + .sdc-workspace-top-bar { + height: @action_nav_height; + padding: 12px 10px 0 50px; + border-bottom: 1px solid @main_color_o; + display: flex; + justify-content: space-between; + white-space: nowrap; + overflow-x: auto; + overflow-y: hidden; + + .progress-container { + flex-grow: 4; + z-index: 1; + display: inline-block; + + .general-view-top-progress { + width: 30%; + margin: 0 auto; + min-width: 140px; + } + } + + .not-latest { + position: absolute; + left: 24px; + top: 20px; + .sprite-new; + .asdc-warning; + display: inline-block; + } + + .sdc-workspace-top-bar-buttons { + + > button, > span:not(.delimiter) { + margin-right: 10px; + vertical-align: middle; + .hand; + + &.sprite-new { + text-indent: 100%; + } + + &.disabled, &:hover.disabled { + pointer-events: none; + } + } + + .delimiter { + height: 32px; + width: 1px; + background-color: @main_color_o; + display: inline-block; + vertical-align: middle; + margin-right: 20px; + } + + display: inline-block; + + } + } + + .workspace-tab-title { + height: 110px; + padding-left: 100px; + line-height: 110px; + .f-type ._28; + } + + .w-sdc-main-container-body-content { + align-items: center; + padding: 0 100px 20px 100px; + + &.third-party { + text-align: left; + padding: 0; + position: absolute; + top: @action_nav_height + @tab_title; + left: 0; + right: 0; + bottom: 0; + } + } + + .w-sdc-main-container-body-content-wrapper { + overflow: auto; + height: calc(~'100% - @{action_nav_height}'); + + .w-sdc-main-container-body-content-header { + display: flex; + + .workspace-tab-title { + flex-grow: 1; + } + + .w-sdc-main-container-body-content-action-buttons { + margin: 72px 100px 0 0; + + > * { + display: inline-block; + vertical-align: middle; + } + + .revert-btn { + text-indent: 100%; + } + + .save-btn { + text-indent: 100%; + } + } + } + } + } +} + 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 new file mode 100644 index 0000000000..8450da829b --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.spec.ts @@ -0,0 +1,122 @@ +/* + * - + * ============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 {TypeWorkspaceComponent} from './type-workspace.component'; +import {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"; +import {TranslateService} from "../../shared/translator/translate.service"; +import {WorkspaceMenuComponent} from "./workspace-menu/workspace-menu.component"; +import {TypeWorkspaceGeneralComponent} from "./type-workspace-general/type-workspace-general.component"; +import {LayoutModule} from "../../components/layout/layout.module"; +import {CacheService} from "../../services/cache.service"; +import {IAppMenu, SdcMenuToken} from "../../config/sdc-menu.config"; +import {AuthenticationService} from "../../services/authentication.service"; +import {ISdcConfig, SdcConfigToken} from "../../config/sdc-config.config"; +import {States} from "../../../utils/constants"; +import {IUserProperties} from "../../../models/user"; +import {Observable} from "rxjs/Observable"; + +describe('TypeWorkspaceComponent', () => { + let component: TypeWorkspaceComponent; + let fixture: ComponentFixture<TypeWorkspaceComponent>; + let translateServiceMock: Partial<TranslateService> = { + 'languageChangedObservable': Observable.of(), + 'translate': jest.fn() + }; + let dataTypeServiceMock: Partial<DataTypeService>; + let cacheService: Partial<CacheService> = { + 'get': jest.fn(param => { + if (param === 'version') { + return 'version'; + } + if (param === 'user') { + return {}; + } + }) + }; + let stateMock: Partial<ng.ui.IStateService> = { + 'current': { + 'name': States.TYPE_WORKSPACE + } + }; + let stateParamsMock: Partial<ng.ui.IStateParamsService> = {}; + let injectorMock: Partial<ng.auto.IInjectorService> = { + 'get': jest.fn(param => { + if (param === '$state') { + return stateMock; + } + }) + }; + let sdcMenuMock: Partial<IAppMenu> = { + 'component_workspace_menu_option': { + "DataType": [ + {"text": "General", "action": "onMenuItemPressed", "state": "general"} + ] + } + }; + let sdcConfigMock: Partial<ISdcConfig>; + let user: Partial<IUserProperties> = { + 'role': 'DESIGNER' + } + let authenticationService: Partial<AuthenticationService> = { + 'getLoggedinUser': jest.fn(() => { + return user; + }) + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TypeWorkspaceComponent, WorkspaceMenuComponent, TypeWorkspaceGeneralComponent ], + imports: [ + ReactiveFormsModule, + TranslateModule, + UiElementsModule, + LayoutModule + ], + providers: [ + {provide: DataTypeService, useValue: dataTypeServiceMock}, + {provide: TranslateService, useValue: translateServiceMock}, + {provide: CacheService, useValue: cacheService}, + {provide: '$state', useValue: stateMock}, + {provide: '$stateParams', useValue: stateParamsMock}, + {provide: '$injector', useValue: injectorMock}, + {provide: SdcMenuToken, useValue: sdcMenuMock}, + {provide: SdcConfigToken, useValue: sdcConfigMock}, + {provide: AuthenticationService, useValue: authenticationService}, + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TypeWorkspaceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.ts new file mode 100644 index 0000000000..d0d5ae8c69 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.component.ts @@ -0,0 +1,91 @@ +/* + * - + * ============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, Inject, OnInit} from '@angular/core'; +import {MenuItem, MenuItemGroup} from "../../../utils/menu-handler"; +import {CacheService} from "../../services/cache.service"; +import {DataTypeModel} from "../../../models/data-types"; +import {DataTypeService} from "../../services/data-type.service"; + +@Component({ + selector: 'app-type-workspace', + templateUrl: './type-workspace.component.html', + styleUrls: ['./type-workspace.component.less'] +}) +export class TypeWorkspaceComponent implements OnInit { + + private typeMenuItemGroup: MenuItemGroup; + + isLoading: boolean; + disabled: boolean; + isViewOnly: boolean = true; + sdcVersion: string; + breadcrumbsModel: Array<MenuItemGroup> = []; + dataType: DataTypeModel = new DataTypeModel(); + currentMenu: MenuItem; + + constructor(private dataTypeService: DataTypeService, private cacheService: CacheService, + @Inject('$state') private $state: ng.ui.IStateService, + @Inject('$stateParams') private stateParams) { } + + ngOnInit(): void { + this.sdcVersion = this.cacheService.get('version'); + this.typeMenuItemGroup = this.createTypeBreadcrumb(); + this.loadDataType(); + } + + private loadDataType(): void { + if (this.stateParams.id) { + this.dataTypeService.findById(this.stateParams.id).subscribe(dataType => { + this.dataType = dataType; + this.updateTypeBreadcrumb(); + }, error => { + console.debug('Could not find data type %s', this.stateParams.id, error); + this.goToBreadcrumbHome(); + }); + } else { + this.dataType = new DataTypeModel(); + } + } + + private updateTypeBreadcrumb(): void { + this.typeMenuItemGroup.updateSelectedMenuItemText(`Data Type: ${this.dataType.name}`); + } + + private createTypeBreadcrumb(): MenuItemGroup { + const menuItem = new MenuItem(`Data Type: ${this.dataType ? this.dataType.name : ''}`, undefined, undefined, undefined, [], [], false); + return new MenuItemGroup(0, [menuItem]); + } + + goToBreadcrumbHome(): void { + const homeMenuItemGroup: MenuItemGroup = this.breadcrumbsModel[0]; + this.$state.go(homeMenuItemGroup.menuItems[homeMenuItemGroup.selectedIndex].state); + } + + onMenuUpdate(menuItemGroup: MenuItemGroup): void { + this.breadcrumbsModel.push(...[this.typeMenuItemGroup, menuItemGroup]); + } + + onMenuClick(menuItem: MenuItem): void { + this.currentMenu = menuItem; + } + +} 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 new file mode 100644 index 0000000000..d3f391db24 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace.module.ts @@ -0,0 +1,58 @@ +/* + * - + * ============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 {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {TypeWorkspaceComponent} from "./type-workspace.component"; +import {WorkspaceMenuComponent} from "./workspace-menu/workspace-menu.component"; +import {CacheService} from "../../services/cache.service"; +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 {TranslateModule} from "../../shared/translator/translate.module"; +import {DataTypeService} from "../../services/data-type.service"; + +@NgModule({ + imports: [ + CommonModule, + UiElementsModule, + LayoutModule, + UpgradeModule, + ReactiveFormsModule, + TranslateModule, + ], + declarations: [ + TypeWorkspaceComponent, + WorkspaceMenuComponent, + TypeWorkspaceGeneralComponent + ], + providers: [ + CacheService, + WorkspaceMenuComponent, + DataTypeService + ], + entryComponents: [TypeWorkspaceComponent], + exports: [TypeWorkspaceComponent] +}) +export class TypeWorkspaceModule { +} diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.html new file mode 100644 index 0000000000..18c6949b46 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.html @@ -0,0 +1,34 @@ +<!-- + ~ - + ~ ============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========================================================= + --> + +<div class="w-sdc-left-sidebar"> + <div class="menu-header" tooltips [attr.tooltip-content]="menuHeader" [title]="menuHeader"> + {{menuHeader}} + </div> + <div class="i-sdc-designer-sidebar-section-content-item" + [ngClass]="{'selected': isSelected(menuItem)}" + *ngFor="let menuItem of leftBarTabs.menuItems"> + <div class="expand-collapse-menu-box-item-text" ng-class="{'disabled': menuItem.isDisabled }"> + <button [attr.data-tests-id]="menuItem.text + 'LeftSideMenu'" type="button" class="i-sdc-designer-sidebar-section-content-item-service-cat" + (click)="menuItem.callback()" [disabled]="menuItem.disabledCategory">{{menuItem.text}}</button> + </div> + </div> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.less b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.less new file mode 100644 index 0000000000..2df6e6ac8b --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.less @@ -0,0 +1,75 @@ +/* + * - + * ============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/variables.less'; +@import '../../../../../assets/styles/mixins.less'; + +.w-sdc-left-sidebar { + padding: 0; + background-color: @tlv_color_t; + box-shadow: none; + z-index: 2; + border-right: 1px solid @main_color_o; + + .menu-header { + border-bottom: 1px solid @main_color_o; + height: 53px; + .f-type._16_m; + font-weight: 700; + line-height: 53px; + padding-left: 40px; + padding-right: 10px; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + white-space: nowrap; + } + + .i-sdc-designer-sidebar-section-content-item { + .f-type._13_m; + color: @main_color_m; + margin-left: 20px; + padding-left: 20px; + margin-top: 20px; + height: 17px; + .hand; + + &:hover { + color: @func_color_s; + font-weight: 600; + } + + &.selected { + border-left: 4px solid @main_color_a; + color: @main_color_a; + margin-left: 18px; + padding-left: 18px; + font-weight: 600; + + } + } + +} + +.hand { + cursor: pointer; +} diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.spec.ts b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.spec.ts new file mode 100644 index 0000000000..a91258c00e --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.spec.ts @@ -0,0 +1,84 @@ +/* + * - + * ============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 {WorkspaceMenuComponent} from './workspace-menu.component'; +import {CacheService} from "../../../services/cache.service"; +import {States} from "../../../../utils/constants"; +import {IAppMenu} from "../../../../models/app-config"; +import {SdcMenuToken} from "../../../config/sdc-menu.config"; + +describe('WorkspaceMenuComponent', () => { + let component: WorkspaceMenuComponent; + let fixture: ComponentFixture<WorkspaceMenuComponent>; + let cacheService: Partial<CacheService> = { + 'get': jest.fn(param => { + if (param === 'version') { + return 'version'; + } + if (param === 'user') { + return {}; + } + }) + }; + let sdcMenuMock: Partial<IAppMenu> = { + 'component_workspace_menu_option': { + "DataType": [ + {"text": "General", "action": "onMenuItemPressed", "state": "general"} + ] + } + }; + let stateMock: Partial<ng.ui.IStateService> = { + 'current': { + 'name': States.TYPE_WORKSPACE + } + }; + let injectorMock: Partial<ng.auto.IInjectorService> = { + 'get': jest.fn(param => { + if (param === '$state') { + return stateMock; + } + }) + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ WorkspaceMenuComponent ], + providers: [ + {provide: CacheService, useValue: cacheService}, + {provide: '$injector', useValue: injectorMock}, + {provide: SdcMenuToken, useValue: sdcMenuMock} + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(WorkspaceMenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.ts new file mode 100644 index 0000000000..c5e49d4d7d --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/type-workspace/workspace-menu/workspace-menu.component.ts @@ -0,0 +1,110 @@ +/* + * - + * ============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, EventEmitter, Inject, Input, OnInit, Output} from '@angular/core'; +import {MenuItem, MenuItemGroup} from "../../../../utils/menu-handler"; +import {CacheService} from "../../../services/cache.service"; +import {IAppMenu} from "../../../../models/app-config"; +import {IUserProperties} from "../../../../models/user"; +import {SdcMenuToken} from "../../../config/sdc-menu.config"; + +@Component({ + selector: 'app-workspace-menu', + templateUrl: './workspace-menu.component.html', + styleUrls: ['./workspace-menu.component.less'] +}) +export class WorkspaceMenuComponent implements OnInit { + + @Input() menuHeader: string = ''; + @Output() onMenuUpdate: EventEmitter<MenuItemGroup> = new EventEmitter<MenuItemGroup>(); + @Output() onClick: EventEmitter<MenuItem> = new EventEmitter<MenuItem>(); + + private role: string; + private user: IUserProperties; + private $state: ng.ui.IStateService; + private $q: ng.IQService; + + leftBarTabs: MenuItemGroup = new MenuItemGroup(); + + constructor(private cacheService: CacheService, @Inject(SdcMenuToken) private sdcMenu: IAppMenu, @Inject('$injector') $injector) { + this.$state = $injector.get('$state'); + this.$q = $injector.get('$q'); + } + + ngOnInit(): void { + this.user = this.cacheService.get('user'); + this.role = this.user.role; + this.initMenuItems(); + } + + private initMenuItems(): void { + this.leftBarTabs = new MenuItemGroup(); + const menuItemsObjects: MenuItem[] = this.updateMenuItemByRole(this.sdcMenu.component_workspace_menu_option["DataType"], this.role); + + this.leftBarTabs.menuItems = menuItemsObjects.map((item: MenuItem) => { + const menuCallback = () => this[menuItem.action](menuItem); + const menuItem = new MenuItem(item.text, menuCallback, item.state, item.action, item.params, item.blockedForTypes, item.disabledCategory); + if (menuItem.params) { + menuItem.params.state = menuItem.state; + } else { + menuItem.params = {state: menuItem.state}; + } + return menuItem; + }); + this.updateSelectedMenuItem(); + this.onMenuUpdate.emit(this.leftBarTabs); + } + + isSelected(menuItem: MenuItem): boolean { + return this.leftBarTabs.selectedIndex === this.leftBarTabs.menuItems.indexOf(menuItem); + } + + private onMenuItemPressed(menuItem: MenuItem): angular.IPromise<boolean> { + this.leftBarTabs.selectedIndex = this.leftBarTabs.menuItems.indexOf(menuItem); + this.onClick.emit(this.leftBarTabs.menuItems[this.leftBarTabs.selectedIndex]); + const deferred: ng.IDeferred<boolean> = this.$q.defer(); + deferred.resolve(true); + return deferred.promise; + } + + private updateMenuItemByRole(menuItems: MenuItem[], role: string): MenuItem[] { + const filteredMenuItems: MenuItem[] = []; + menuItems.forEach((item: any) => { + if (!(item.disabledRoles && item.disabledRoles.indexOf(role) > -1)) { + filteredMenuItems.push(item); + } + }); + return filteredMenuItems; + } + + private updateSelectedMenuItem(): void { + const stateArray: Array<string> = this.$state.current.name.split('.', 2); + const stateWithoutInternalNavigate: string = stateArray[0] + '.' + stateArray[1]; + const selectedItem: MenuItem = this.leftBarTabs.menuItems.find((item: MenuItem) => { + let itemStateArray: Array<string> = item.state.split('.', 2); + let itemStateWithoutNavigation: string = itemStateArray[0] + '.' + itemStateArray[1]; + return (itemStateWithoutNavigation === stateWithoutInternalNavigate); + }); + this.leftBarTabs.selectedIndex = selectedItem ? this.leftBarTabs.menuItems.indexOf(selectedItem) : 0; + this.onClick.emit(this.leftBarTabs.menuItems[this.leftBarTabs.selectedIndex]); + } + +} diff --git a/catalog-ui/src/app/ng2/services/cookie.service.ts b/catalog-ui/src/app/ng2/services/cookie.service.ts index 61d13186fa..22c1dd310f 100644 --- a/catalog-ui/src/app/ng2/services/cookie.service.ts +++ b/catalog-ui/src/app/ng2/services/cookie.service.ts @@ -18,9 +18,9 @@ * ============LICENSE_END========================================================= */ -import {Injectable, Inject} from '@angular/core'; +import {Inject, Injectable} from '@angular/core'; import {ICookie} from "../../models/app-config"; -import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; +import {ISdcConfig, SdcConfigToken} from "../config/sdc-config.config"; @Injectable() export class Cookie2Service { @@ -36,7 +36,6 @@ export class Cookie2Service { if ((junctionName !== null) && (junctionName !== '')) { this.cookiePrefix = this.cookie.prefix + junctionName + '!'; } - console.log("junctionName:" + junctionName); } private getCookieByName = (cookieName:string):string => { diff --git a/catalog-ui/src/app/ng2/services/data-type.service.ts b/catalog-ui/src/app/ng2/services/data-type.service.ts index 70555a5efd..bf500ec16e 100644 --- a/catalog-ui/src/app/ng2/services/data-type.service.ts +++ b/catalog-ui/src/app/ng2/services/data-type.service.ts @@ -19,11 +19,15 @@ */ import * as _ from "lodash"; -import { Injectable } from '@angular/core'; +import {Inject, Injectable} from '@angular/core'; import { DataTypeModel, DataTypesMap, PropertyFEModel, DerivedFEProperty} from "app/models"; import { DataTypesService } from "app/services/data-types-service"; import { PROPERTY_DATA } from "app/utils"; import {DerivedFEAttribute} from "../../models/attributes-outputs/derived-fe-attribute"; +import {ISdcConfig} from "../config/sdc-config.config.factory"; +import {SdcConfigToken} from "../config/sdc-config.config"; +import {HttpClient} from "@angular/common/http"; +import {Observable} from "rxjs/Observable"; /** This is a new service for NG2, to eventually replace app/services/data-types-service.ts * @@ -34,11 +38,16 @@ import {DerivedFEAttribute} from "../../models/attributes-outputs/derived-fe-att @Injectable() export class DataTypeService { public dataTypes: DataTypesMap; + private readonly baseUrl: string; + private readonly dataTypeUrl: string; - constructor(private dataTypeService: DataTypesService) { + constructor(private dataTypeService: DataTypesService, private httpClient: HttpClient, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) { this.dataTypes = dataTypeService.getAllDataTypes(); //This should eventually be replaced by an NG2 call to the backend instead of utilizing Angular1 downgraded component. + this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root; + this.dataTypeUrl = `${this.baseUrl}data-types` } + public getDataTypeByModelAndTypeName(modelName: string, typeName: string): DataTypeModel { this.dataTypes = this.dataTypeService.getAllDataTypesFromModel(modelName); let dataTypeFound = this.dataTypes[typeName]; @@ -64,6 +73,11 @@ export class DataTypeService { return this.dataTypeService.findAllDataTypesByModel(modelName); } + public findById(id: string): Observable<DataTypeModel> { + const url = `${this.dataTypeUrl}/${id}` + return this.httpClient.get<DataTypeModel>(url); + } + public getConstraintsByParentTypeAndUniqueID(rootPropertyType, propertyName){ // const property = this.dataTypes[rootPropertyType].properties.filter(property => // property.name == propertyName); diff --git a/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts b/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts index aab531d205..a3c04bc87b 100644 --- a/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts +++ b/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts @@ -21,14 +21,13 @@ /** * Created by rc2122 on 4/6/2017. */ -import { DataTypesService } from "../../services/data-types-service"; -import ICacheObject = angular.ICacheObject; -import { CookieService } from "../../services/cookie-service"; +import {DataTypesService} from "../../services/data-types-service"; +import {CookieService} from "../../services/cookie-service"; import {ComponentFactory} from "../../utils/component-factory" -import { EventListenerService } from "app/services/event-listener-service"; -import { ModalsHandler } from "app/utils"; -import IScope = angular.IScope; -import { SharingService } from "../services/sharing.service"; +import {EventListenerService} from "app/services/event-listener-service"; +import {ModalsHandler} from "app/utils"; +import {SharingService} from "../services/sharing.service"; +import ICacheObject = angular.ICacheObject; /** Services we need to upgrade from angular1 to angular2 - in the future we need to rewrite them all to angular2 **/ @@ -115,12 +114,6 @@ export const StateParamsServiceFactory = { useFactory: stateParamsServiceFactory, deps: ['$injector'] }; -// -// export const EventListenerServiceProvider = { -// provide: EventListenerService, -// useFactory: eventListenerServiceServiceFactory, -// deps: ['$injector'] -// }; export const NotificationServiceProvider = { provide: 'Notification', |