diff options
Diffstat (limited to 'catalog-ui/src/app/ng2')
148 files changed, 2901 insertions, 442 deletions
diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts index 88c2d876c4..291768a500 100644 --- a/catalog-ui/src/app/ng2/app.module.ts +++ b/catalog-ui/src/app/ng2/app.module.ts @@ -27,7 +27,7 @@ import {UpgradeAdapter} from '@angular/upgrade'; import {UpgradeModule} from '@angular/upgrade/static'; import {PropertiesAssignmentModule} from './pages/properties-assignment/properties-assignment.module'; import { - DataTypesServiceProvider, SharingServiceProvider, CookieServiceProvider, + DataTypesServiceProvider, SharingServiceProvider, CookieServiceProvider, StateServiceFactory, StateParamsServiceFactory, CacheServiceProvider, EventListenerServiceProvider } from "./utils/ng1-upgraded-provider"; import {ConfigService} from "./services/config.service"; @@ -38,9 +38,14 @@ import {Cookie2Service} from "./services/cookie.service"; import {ComponentServiceNg2} from "./services/component-services/component.service"; import {ServiceServiceNg2} from "./services/component-services/service.service"; import {ComponentInstanceServiceNg2} from "./services/component-instance-services/component-instance.service"; -import { XHRBackend, RequestOptions } from '@angular/http'; -import { SearchBarComponent } from './shared/search-bar/search-bar.component'; -import { SearchWithAutoCompleteComponent } from './shared/search-with-autocomplete/search-with-autocomplete.component'; +import {ModalService} from "./services/modal.service"; +import {UiElementsModule} from "./components/ui/ui-elements.module"; +import {ConnectionWizardModule} from "./pages/connection-wizard/connection-wizard.module"; +import {LayoutModule} from "./components/layout/layout.module"; +import {UserService} from "./services/user.service"; +import {SdcConfig} from "./config/sdc-config.config"; +import { TranslateModule } from "./shared/translator/translate.module"; +import { TranslationServiceConfig } from "./config/translation.service.config"; export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule)); @@ -51,23 +56,28 @@ export function configServiceFactory(config:ConfigService) { @NgModule({ declarations: [ - AppComponent, - SearchBarComponent, - SearchWithAutoCompleteComponent + AppComponent ], imports: [ BrowserModule, UpgradeModule, FormsModule, HttpModule, + LayoutModule, + TranslateModule, + UiElementsModule, + + //We need to import them here since we use them in angular1 + ConnectionWizardModule, PropertiesAssignmentModule ], exports: [], - entryComponents: [SearchWithAutoCompleteComponent], + entryComponents: [], providers: [ DataTypesServiceProvider, SharingServiceProvider, CookieServiceProvider, + StateServiceFactory, StateParamsServiceFactory, CacheServiceProvider, EventListenerServiceProvider, @@ -75,9 +85,13 @@ export function configServiceFactory(config:ConfigService) { Cookie2Service, ConfigService, ComponentServiceNg2, + ModalService, ServiceServiceNg2, HttpService, + UserService, + SdcConfig, ComponentInstanceServiceNg2, + TranslationServiceConfig, { provide: APP_INITIALIZER, useFactory: configServiceFactory, @@ -90,9 +104,8 @@ export function configServiceFactory(config:ConfigService) { export class AppModule { - // ngDoBootstrap() {} - constructor(public upgrade:UpgradeModule) { + constructor(public upgrade:UpgradeModule) { } } diff --git a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.html b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.html new file mode 100644 index 0000000000..37686342e8 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.html @@ -0,0 +1,7 @@ +<menu-list [open]="props?.open" [position]="props?.position" [styleClass]="props?.styleClass"> + <menu-item *ngFor="let item of props?.items" + [action]="item?.action" + [styleClass]="item?.styleClass"> + {{ item?.contents }} + </menu-item> +</menu-list> diff --git a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts new file mode 100644 index 0000000000..85d1899d96 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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, Input } from '@angular/core'; + +declare var window:any; +@Component({ + selector: 'canvas-menu', + templateUrl: './menu-list-ng2.component.html' +}) +export class MenuListNg2Component { + @Input() props:any = { + items: [] + }; + + constructor() { + window.menu2 = this; + } +} diff --git a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.module.ts b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.module.ts new file mode 100644 index 0000000000..957ba35c5a --- /dev/null +++ b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from '@angular/common'; +import { MenuListModule } from "../../ui/menu/menu-list.module"; +import { MenuListNg2Component } from "./menu-list-ng2.component"; + +export { + MenuListNg2Component +}; + +@NgModule({ + declarations: [ + MenuListNg2Component + ], + imports: [CommonModule, MenuListModule], + exports: [ + MenuListNg2Component + ], + entryComponents: [ //need to add anything that will be dynamically created + MenuListNg2Component +] +}) +export class MenuListNg2Module { +} diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html deleted file mode 100644 index a3e28c5f0b..0000000000 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html +++ /dev/null @@ -1 +0,0 @@ -<input #{{name}} [(ngModel)]="value" type="checkbox" (change)="onSave(value)" [ngClass]="{'disabled':readonly}"/> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.less b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.less deleted file mode 100644 index bed097fe5e..0000000000 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.less +++ /dev/null @@ -1,2 +0,0 @@ -/deep/ ui-element-checkbox { -} diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html deleted file mode 100644 index bfb927af71..0000000000 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html +++ /dev/null @@ -1,3 +0,0 @@ -<select name='{{name}}' [(ngModel)]="value" #t (change)="onSave()" [ngClass]="{'disabled':readonly}"> - <option *ngFor="let ddvalue of values" [value]="ddvalue.value">{{ddvalue.label}}</option> -</select> diff --git a/catalog-ui/src/app/ng2/components/layout/layout.module.ts b/catalog-ui/src/app/ng2/components/layout/layout.module.ts new file mode 100644 index 0000000000..827209326c --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/layout.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { FormsModule } from "@angular/forms"; +import { TranslateModule } from "../../shared/translator/translate.module"; +import { TopNavComponent } from "./top-nav/top-nav.component"; + +@NgModule({ + declarations: [ + TopNavComponent + ], + imports: [ + CommonModule, + FormsModule, + TranslateModule + ], + exports: [], + entryComponents: [ //need to add anything that will be dynamically created + TopNavComponent + ], + providers: [] +}) +export class LayoutModule { + +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html new file mode 100644 index 0000000000..55c4bf0460 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html @@ -0,0 +1,53 @@ +<nav class="top-nav"> + + <div class="asdc-app-title-wrapper"> + <a class="asdc-app-title">{{ 'PROJECT_TITLE'|translate }}</a> + <div class="asdc-version"> v.{{version}}</div> + </div> + + <ul class="top-menu" *ngIf="!menuModel && topLvlMenu"> + <!-- no hierarchy & dropdowns mode --> + <li *ngFor="let item of topLvlMenu.menuItems; let i = index" + [ngClass]="{'selected': i == topLvlMenu.selectedIndex}"> + <a (click)="menuItemClick(topLvlMenu, item)" + [attr.data-tests-id]="'main-menu-button-' + item.text.toLowerCase()">{{item.text}}</a> + </li> + </ul> + + <ul class="top-menu" *ngIf="menuModel"> + <!-- with hierarchy & dropdowns mode --> + <ng-container *ngFor="let groupItem of menuModel; let $index = index; let $last = last"> + <li [ngClass]="{'selected': $last }"> + <a (click)="menuItemClick(groupItem, groupItem.menuItems[groupItem.selectedIndex])" + [attr.data-tests-id]="'breadcrumbs-button-' + $index"> + {{groupItem.menuItems[groupItem.selectedIndex].text}} + </a> + </li> + <li class="triangle-dropdown" + [ngClass]="{'item-click': groupItem.itemClick}" (mouseover)="groupItem.itemClick = true"> + <div class="triangle"><span class="sprite-new arrow-right"></span></div> + <ul class="sub-menu"> + <li *ngFor="let ddItem of groupItem.menuItems; let $index2 = index" + (click)="menuItemClick(groupItem, ddItem)" + [ngClass]="{'selected': $index2 == groupItem.selectedIndex, 'disabled': ddItem.isDisabled}" + [attr.data-tests-id]="'sub-menu-button-' + ddItem.text.toLowerCase()"> + <span sdc-smart-tooltip="">{{ddItem.text}}</span> + </li> + </ul> + </li> + </ng-container> + </ul> + + <div class="top-search" [hidden]="hideSearch === true"> + <input type="text" + class="search-text" + placeholder="Search" + [ngModel]="searchTerm" + (ngModelChange)="emitSearchTerm($event)" + data-tests-id="main-menu-input-search" /> + <span class="w-sdc-search-icon magnification"></span> + </div> + + <div class="notification-icon" [ngClass]="{'disabled' : progress > 0}" *ngIf="user.role === 'DESIGNER' && notificationIconCallback" (click)="notificationIconCallback()" tooltip="Vendor Software Product Repository" tooltipPlacement="left" data-tests-id="repository-icon"></div> + +</nav> diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less new file mode 100644 index 0000000000..dc666cbf00 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less @@ -0,0 +1,225 @@ +@import "../../../../../assets/styles/variables"; +@import "../../../../../assets/styles/variables-old"; +@import "../../../../../assets/styles/mixins_old"; +@import "../../../../../assets/styles/sprite"; + +.top-nav { + position: fixed; + top: @header_height; + background-color: @main_color_p; + .box-shadow(0px 1px 3px 0px rgba(0, 0, 0, 0.33)); + width: 100%; + height: @top_nav_height; + line-height: @top_nav_height; + z-index: 10; + display: flex; + flex-direction: row; + align-items: center; + + .asdc-app-title-wrapper { + flex-grow: 1; + line-height: 16px; + margin: 0 20px; + + a.asdc-app-title { + //.m_18_r; + text-decoration: none; + } + + .asdc-version { + //.m_12_r; + .opacity(0.8); + line-height: 14px; + flex-grow: 1; + } + + } + + ul.top-menu { + list-style-type: none; + margin: 0 0 0 20px; + padding: 0; + flex-grow: 999; + + & > li { + float: left; + cursor: pointer; + line-height: 50px; + height: 50px; + padding: 0 20px; + + &.selected { + border-bottom: solid 4px @main_color_a; + + a { + color: @func_color_s; + } + } + + /*&:hover { + border-bottom: solid 4px @main_color_a; + }*/ + + a { + font-family: @font-opensans-medium; + color: @main_color_m; + font-size: 16px; + display: block; + text-align: center; + text-decoration: none; + } + + &.triangle-dropdown { + padding: 0; + position: relative; + + div.triangle { + margin-top: 15px; + border-radius: 2px; + width: 17px; + height: 18px; + + //temp use - until new triangle gets in + line-height: 18px; + text-align: center; + font-size: 10px; + + &:hover { + background-color: rgba(156, 156, 156, 0.2); + + span { + .arrow-right-hover; + } + } + } + + + li a { + font-size: 16px; + } + + ul.sub-menu { + .perfect-scrollbar; + position: absolute; + left: 0; + top: 40px; + z-index: 1; + + overflow-x: hidden; + overflow-y: auto; + max-height: 0; + -webkit-transition: max-height 200ms ease-in; + -moz-transition: max-height 200ms ease-in; + -o-transition: max-height 200ms ease-in; + transition: max-height 200ms ease-in; + + padding: 0; + background-color: white; + visibility: hidden; + + li { + + height: 35px; + background-color: white; + font-size: 13px; + width: 150px; + line-height: 35px; + padding: 0 10px; + + &.disabled { + opacity: 1; + } + &.selected { + background-color: @tlv_color_v; + font-weight: bold; + } + &:hover { + color: @main_color_a; + } + span { + height: 35px; + width: 130px; + display: inline; + white-space: nowrap; + overflow: hidden; + } + } + } + &.item-click:hover ul.sub-menu, + &.item-click:active ul.sub-menu { + visibility: visible; + max-height: 500px; + border: 1px solid @func_color_b; + border-radius: 2px; + box-shadow: 0px 2px 2px 0px rgba(24, 24, 25, 0.1); + + div ul { + + } + } + } + } + + } + + .top-search { + position: relative; + flex-grow: 1; + padding: 0 20px; + + input.search-text { + .border-radius(2px); + width: 245px; + height: 32px; + line-height: 32px; + border: 1px solid @main_color_o; + outline: none; + text-indent: 10px; + + &::-webkit-input-placeholder { font-style: italic; } /* Safari, Chrome and Opera */ + &:-moz-placeholder { font-style: italic; } /* Firefox 18- */ + &::-moz-placeholder { font-style: italic; } /* Firefox 19+ */ + &:-ms-input-placeholder { font-style: italic; } /* IE 10+ */ + &:-ms-input-placeholder { font-style: italic; } /* Edge */ + /* font-style: italic; + }*/ + /* Firefox 18- */ + &::-moz-placeholder { + font-style: italic; + } + /* Firefox 19+ */ + &:-ms-input-placeholder { + font-style: italic; + } + /* IE 10+ */ + &:-ms-input-placeholder { + font-style: italic; + } + /* Edge */ + } + + .magnification { + position: absolute; + top: 19px; + right: 26px; + } + + } + + .notification-icon { + cursor: pointer; + flex-grow: 1; + margin: 0 10px 6px 0; + .sprite-new; + .vsp-list-icon; + + &:hover { + .vsp-list-icon-hover; + } + + &:active { + .vsp-list-icon-active; + } + + } + +} 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 new file mode 100644 index 0000000000..f48aa4801f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts @@ -0,0 +1,149 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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, Inject, Input, Output, EventEmitter} from "@angular/core"; +import {IHostedApplication, IUserProperties} from "app/models"; +import {MenuItemGroup, MenuItem} from "app/utils"; +import {UserService} from "../../../services/user.service"; +import {SdcConfigToken, ISdcConfig} from "../../../config/sdc-config.config"; +import {TranslateService} from "../../../shared/translator/translate.service"; + + +declare const window:any; +@Component({ + selector: 'top-nav', + templateUrl: './top-nav.component.html', + styleUrls:['./top-nav.component.less'] +}) +export class TopNavComponent { + @Input() public version:string; + @Input() public menuModel:Array<MenuItemGroup>; + @Input() public topLvlSelectedIndex:number; + @Input() public hideSearch:boolean; + @Input() public searchTerm:string; + @Input() public notificationIconCallback:Function; + @Output() public searchTermChange:EventEmitter<string> = new EventEmitter<string>(); + emitSearchTerm(event:string) { + this.searchTermChange.emit(event); + } + + public topLvlMenu:MenuItemGroup; + public user:IUserProperties; + + constructor(private translateService:TranslateService, + @Inject('$state') private $state:ng.ui.IStateService, + private userService:UserService, + @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { + window.nav = this; + } + + private _getTopLvlSelectedIndexByState = ():number => { + if (!this.topLvlMenu.menuItems) { + return 0; + } + + let result = -1; + + //set result to current state + this.topLvlMenu.menuItems.forEach((item:MenuItem, index:number)=> { + if (item.state === this.$state.current.name) { + result = index; + } + }); + + //if it's a different state , checking previous state param + if (result === -1) { + this.topLvlMenu.menuItems.forEach((item:MenuItem, index:number)=> { + if (item.state === this.$state.params['previousState']) { + result = index; + } + }); + } + + if (result === -1) { + result = 0; + } + + return result; + }; + + ngOnChanges(changes) { + if (changes['menuModel']) { + console.log('menuModel was changed!'); + this.generateMenu(); + } + } + + ngOnInit() { + console.log('Nav is init!', this.menuModel); + this.user = this.userService.getLoggedinUser(); + + this.translateService.languageChangedObservable.subscribe((lang) => { + let tmpArray: Array<MenuItem> = [ + new MenuItem(this.translateService.translate("TOP_MENU_HOME_BUTTON"), null, "dashboard", "goToState", null, null), + new MenuItem(this.translateService.translate("TOP_MENU_CATALOG_BUTTON"), null, "catalog", "goToState", null, null) + ]; + + // Only designer can perform onboarding + if (this.user && this.user.role === 'DESIGNER') { + tmpArray.push(new MenuItem(this.translateService.translate("TOP_MENU_ON_BOARD_BUTTON"), null, "onboardVendor", "goToState", null, null)); + _.each(this.sdcConfig.hostedApplications, (hostedApp: IHostedApplication) => { + if (hostedApp.exists) { + tmpArray.push(new MenuItem(hostedApp.navTitle, null, hostedApp.defaultState, "goToState", null, null)); + } + }); + } + + this.topLvlMenu = new MenuItemGroup(0, tmpArray, true); + this.topLvlMenu.selectedIndex = isNaN(this.topLvlSelectedIndex) ? this._getTopLvlSelectedIndexByState() : this.topLvlSelectedIndex; + + this.generateMenu(); + }); + } + + generateMenu() { + if (this.menuModel && this.topLvlMenu && this.menuModel[0] !== this.topLvlMenu) { + this.menuModel.unshift(this.topLvlMenu); + } + } + + goToState(state:string, params:Array<any>):Promise<boolean> { + return new Promise((resolve, reject) => { + this.$state.go(state, params && params.length > 0 ? [0] : undefined); + resolve(true); + }); + } + + menuItemClick(itemGroup:MenuItemGroup, item:MenuItem) { + itemGroup.itemClick = false; + + let onSuccess = ():void => { + itemGroup.selectedIndex = itemGroup.menuItems.indexOf(item); + }; + let onFailed = ():void => { + }; + + if (item.callback) { + (item.callback.apply(undefined, item.params)).then(onSuccess, onFailed); + } else { + this[item.action](item.state, item.params).then(onSuccess, onFailed); + } + } +} diff --git a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.html b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html index 4d2b91f3b4..ddda82ab58 100644 --- a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.html +++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html @@ -4,7 +4,7 @@ <div class="field"> <label>Resource Type</label> <div> - <checkbox [label]="'All'" [(checked)]="allSelected" (checkedChange)="selectAll()"></checkbox> + <checkbox [label]="'All'" [(checked)]="allSelected" (checkedChange)="selectAll()" data-tests-id="filter-checkbox-all"></checkbox> </div> <div *ngFor="let type of typesOptions"> <checkbox [label]="type" [(checked)]="selectedTypes[type]" (checkedChange)="onTypeSelected(type)"></checkbox> @@ -17,10 +17,11 @@ [(ngModel)]="filterData.propertyName" placeholder="Type here" required + data-tests-id="filter-box" /> </div> </form> </popover-content> <div class="open-filter-button" [popover]="filterPopover" [ngClass]="{'open':showPopover}" (onShown)="showPopover = true" (onHidden)="showPopover = false"> - <div class="sprite-new filter-icon"></div> + <div class="sprite-new filter-icon" data-tests-id="filter-button"></div> </div> diff --git a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.less b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.less index 07f38d3011..25c1467b3b 100644 --- a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.less +++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.less @@ -1,4 +1,4 @@ -@import '../../../../assets/styles/variables'; +@import '../../../../../assets/styles/variables'; form{ margin: 0 20px; .field{ diff --git a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.ts b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.ts index c43c30db21..5a9bfbcecb 100644 --- a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.ts @@ -23,8 +23,8 @@ */ import {Component, Input, Output, EventEmitter, ViewChild} from '@angular/core'; import {ButtonModel, ButtonsModelMap, FilterPropertiesAssignmentData} from "app/models"; -import {PopoverComponent} from "../popover/popover.component"; -import * as sdcConfig from "../../../../../configurations/dev" +import * as sdcConfig from "../../../../../../configurations/dev" +import {PopoverComponent} from "../../ui/popover/popover.component"; @Component({ selector: 'filter-properties-assignment', diff --git a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-display-options.ts b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-display-options.ts index c8d4566653..c8d4566653 100644 --- a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-display-options.ts +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-display-options.ts diff --git a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.html b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.html index 40a1c37cee..c3f9e5ac74 100644 --- a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.html +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.html @@ -1,7 +1,7 @@ <div class="navigation-wrapper"> <div class="node-item" *ngFor="let item of displayData" (click)="onClick($event, item)"> <div class="node-data-wrapper" [ngClass]="{'selected': selectedItem && selectedItem === item[displayOptions.idProperty]}"> - <span class="node-data" [ngClass]="{'mark':item[displayOptions.valueProperty] === displayOptions.searchText}">{{item[displayOptions.valueProperty]}}</span> + <span class="node-data" [ngClass]="{'mark':item[displayOptions.valueProperty] === displayOptions.searchText}" [attr.data-tests-id]="item[displayOptions.valueProperty]">{{item[displayOptions.valueProperty]}}</span> </div> <div class="children-node" *ngIf="item[displayOptions.childrenProperty]"> <hierarchy-navigation class="children-hierarchy" [displayData]="item[displayOptions.childrenProperty]" diff --git a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.less b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.less index 4befa2c797..4befa2c797 100644 --- a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.less +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.less diff --git a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.ts b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts index dc0a02c277..dc0a02c277 100644 --- a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html index 2b58d0f086..57e0474c66 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html @@ -37,7 +37,7 @@ [readonly]="readonly"> </dynamic-element> <div class="delete-button-container"> - <span *ngIf="input.instanceUniqueId && !readonly" class="sprite-new delete-btn" (click)="openDeleteModal(input)"></span> + <span *ngIf="input.instanceUniqueId && !readonly" class="sprite-new delete-btn" (click)="openDeleteModal(input)" data-tests-id="delete-input-button"></span> </div> </div> diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less index 89c7287449..0545874f53 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less @@ -1,5 +1,5 @@ -@import './../../../../assets/styles/variables.less'; +@import './../../../../../assets/styles/variables.less'; :host /deep/ input { width:100%;} diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts index 736655f3f7..0add1cd707 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts @@ -21,16 +21,14 @@ /** * Created by rc2122 on 5/4/2017. */ -import {Component, Input, Output, EventEmitter, ViewChild} from "@angular/core"; +import {Component, Input, Output, EventEmitter} from "@angular/core"; import {InputFEModel} from "app/models"; -import { ModalService } from 'app/ng2/services/modal.service'; - - +import {ModalService} from "../../../services/modal.service"; @Component({ selector: 'inputs-table', templateUrl: './inputs-table.component.html', - styleUrls: ['../inputs-table/inputs-table.component.less'] + styleUrls: ['../inputs-table/inputs-table.component.less'], }) export class InputsTableComponent { diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html index 3ffc9c16be..14b6c7d4c0 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html @@ -1,11 +1,11 @@ <div *ngIf="!property.hidden" class="dynamic-property-row nested-level-{{nestedLevel}}" [@fadeIn] - [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.propertiesName }" + [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.propertiesName, 'readonly': property.isDisabled ||property.isDeclared}" [class.with-top-border]="property.isChildOfListOrMap" (click)="onClickPropertyRow(property, $event)"> <!-- LEFT CELL --> <ng-container *ngIf="!isPropertyFEModel"> <div class="table-cell" *ngIf="canBeDeclared" [ngClass]="{'filtered':property.name === propertyNameSearchText}" [class.round-checkbox]="property.isDeclared"> <!-- simple children of complex type [@checkEffect]="property.isDeclared"--> - <checkbox [(checked)]="property.isSelected" [disabled]="property.isDisabled ||property.isDeclared || readonly" (checkedChange)="checkProperty.emit(property.propertiesName)" ></checkbox> + <checkbox *ngIf="hasDeclareOption" [(checked)]="property.isSelected" [disabled]="property.isDisabled ||property.isDeclared || readonly" (checkedChange)="checkProperty.emit(property.propertiesName)" ></checkbox> <div class="inner-cell-div" tooltip="{{property.name}}"><span>{{property.name}}</span></div> </div> <div class="table-cell" *ngIf="!canBeDeclared && !property.isChildOfListOrMap">{{property.name}}</div> <!-- simple children of complex type within map or list --> @@ -47,7 +47,8 @@ <ng-container *ngFor="let prop of property.flattenedChildren | filterChildProperties: expandedChildId; trackBy:prop?.propertiesName"> <dynamic-property [selectedPropertyId]="selectedPropertyId" - [canBeDeclared]="prop.canBeDeclared" + [hasDeclareOption]="hasDeclareOption" + [canBeDeclared]="hasDeclareOption && prop.canBeDeclared" [property]="prop" [expandedChildId]="expandedChildId" [propertyNameSearchText]="propertyNameSearchText" diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less index 48d3d035d0..0adce2c99d 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less @@ -1,4 +1,4 @@ -@import '../../../../../assets/styles/variables.less'; +@import '../../../../../../assets/styles/variables.less'; .flat-children-container { .dynamic-property-row { /*create nested left border classes for up to 10 levels of nesting*/ @@ -25,6 +25,15 @@ 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; @@ -72,3 +81,4 @@ outline: none; box-sizing: border-box; } + diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts index 9cf043098b..04cb26d030 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts @@ -19,11 +19,11 @@ */ import {Component, Input, Output, EventEmitter} from "@angular/core"; -import { PropertyBEModel, PropertyFEModel, DerivedFEProperty, DerivedPropertyType, SchemaPropertyGroupModel, DataTypeModel } from "app/models"; -import { PROPERTY_DATA, PROPERTY_TYPES } from 'app/utils'; -import { PropertiesUtils } from "app/ng2/pages/properties-assignment/properties.utils"; -import { DataTypeService } from "../../../services/data-type.service"; +import { PropertyFEModel, DerivedFEProperty, DerivedPropertyType } from "app/models"; +import { PROPERTY_TYPES } from 'app/utils'; +import { DataTypeService } from "../../../../services/data-type.service"; import { trigger, state, style, transition, animate } from '@angular/core'; +import {PropertiesUtils} from "../../../../pages/properties-assignment/services/properties.utils"; @Component({ @@ -47,6 +47,7 @@ export class DynamicPropertyComponent { @Input() propertyNameSearchText: string; @Input() readonly: boolean; @Input() hasChildren: boolean; + @Input() hasDeclareOption:boolean; @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); @Output() expandChild: EventEmitter<string> = new EventEmitter<string>(); diff --git a/catalog-ui/src/app/ng2/pipes/filterChildProperties.pipe.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/pipes/filterChildProperties.pipe.ts index 4520469594..4520469594 100644 --- a/catalog-ui/src/app/ng2/pipes/filterChildProperties.pipe.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/pipes/filterChildProperties.pipe.ts diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html index a9dc499e7d..933b80f577 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.html +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html @@ -2,38 +2,38 @@ <loader [display]="isLoading" [size]="'large'" [relative]="true" [loaderDelay]="500"></loader> <div class="table-header"> <div class="table-cell col1">Property Name</div> - <div class="table-cell col2">Type</div> - <div class="table-cell col3">ES</div> + <div class="table-cell col2" *ngIf="!hidePropertyType">Type</div> + <div class="table-cell col3" *ngIf="!hidePropertyType">ES</div> <div class="table-cell valueCol">Value</div> </div> - <div class="table-body"> + <div class="table-body" [ngClass]="{'view-mode': readonly}"> <div class="no-data" *ngIf="!fePropertiesMap || !(fePropertiesMap | keys).length">No data to display</div> <ng-container *ngFor="let instanceId of fePropertiesMap | keys; trackBy:instanceId"> - <div class="table-rows-header white-sub-header">{{feInstanceNamesMap[instanceId]}}</div> + <div class="table-rows-header white-sub-header" *ngIf="feInstanceNamesMap">{{feInstanceNamesMap[instanceId]}}</div> <div class="table-row" *ngFor="let property of fePropertiesMap[instanceId] | searchFilter:'name':searchTerm; trackBy:property?.name" (click)="onClickPropertyRow(property, instanceId, $event)" - [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.name }"> + [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.name, 'readonly': property.isDisabled || property.isDeclared}"> <div class="table-cell col1" [ngClass]="{'filtered':property.name === propertyNameSearchText}" [class.round-checkbox]="property.isDeclared"> <div class="property-name"> - <checkbox [(checked)]="property.isSelected" + <checkbox *ngIf="hasDeclareOption" [(checked)]="property.isSelected" [disabled]="property.isDisabled || property.isDeclared || readonly" - (checkedChange)="propertyChecked(property)"></checkbox> + (checkedChange)="propertyChecked(property)" [attr.data-tests-id]="property.name"></checkbox> <div class="inner-cell-div" tooltip="{{property.name}}"> <span>{{property.name}}</span> </div> </div> <span *ngIf="property.description" class="property-description-icon sprite-new show-desc" tooltip="{{property.description}}" tooltipDelay="0"></span> </div> - <div class="table-cell col2"> + <div class="table-cell col2" *ngIf="!hidePropertyType"> <div class="inner-cell-div" tooltip="{{property.type | contentAfterLastDot}}"> <span>{{property.type | contentAfterLastDot}}</span> </div> </div> - <div class="table-cell col3"> + <div class="table-cell col3" *ngIf="!hidePropertyType"> <div *ngIf="property.schema && property.schema.property && property.schema.property.type" class="inner-cell-div" tooltip="{{property.schema.property.type | contentAfterLastDot}}"> <span>{{property.schema.property.type | contentAfterLastDot}}</span> </div> @@ -42,7 +42,8 @@ <!-- [ngClass]="{'filtered':property.name === propertyNameSearchText}" (selectProperty)="propertySelected(property, $event, flatProperty.propertiesName)" [propType]="property.type" [propSchema]="property.schema" [propKey]="" [propValue]="property.value"--> <dynamic-property [selectedPropertyId]="selectedPropertyId" - [canBeDeclared]="true" + [hasDeclareOption]="hasDeclareOption" + [canBeDeclared]="hasDeclareOption && true" [property]="property" [expandedChildId]="property.expandedChildPropertyId" [propertyNameSearchText]="propertyNameSearchText" @@ -56,7 +57,6 @@ </div> </div> - </ng-container> </div> diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.less index 9ede84faff..20da0b6ec2 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.less @@ -1,5 +1,5 @@ -@import './../../../../assets/styles/variables.less'; -@import '../../../../assets/styles/sprite'; +@import './../../../../../assets/styles/variables.less'; +@import '../../../../../assets/styles/sprite'; @smaller-screen: ~"only screen and (max-width: 1580px)"; :host /deep/ input { width:100%;} @@ -43,6 +43,7 @@ flex-direction: column; overflow-y:auto; flex: 1; + background-color: @main_color_p; .no-data { border: #d2d2d2 solid 1px; @@ -55,13 +56,25 @@ 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 { @@ -100,7 +113,8 @@ .property-name { flex: 1; display: flex; - max-width: 90%; + overflow: hidden; + //max-width: 90%; fix bug 327139 } .property-description-icon { diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts index afb7189348..32bbb1b3a0 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts @@ -18,11 +18,9 @@ * ============LICENSE_END========================================================= */ -import { Component, Input, Output, EventEmitter, SimpleChanges, ViewChild, ElementRef } from "@angular/core"; -import {PropertyFEModel, DerivedFEProperty, DerivedPropertyType, InstanceFePropertiesMap} from "app/models"; -import {PropertiesService} from "../../services/properties.service"; -import { DynamicElementComponent } from 'app/ng2/components/dynamic-element/dynamic-element.component'; -import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; +import { Component, Input, Output, EventEmitter} from "@angular/core"; +import {PropertyFEModel, DerivedFEProperty, InstanceFePropertiesMap} from "app/models"; +import {PropertiesService} from "../../../services/properties.service"; @Component({ selector: 'properties-table', @@ -34,24 +32,25 @@ export class PropertiesTableComponent { @Input() fePropertiesMap: InstanceFePropertiesMap; @Input() feInstanceNamesMap: Map<string, string>; @Input() selectedPropertyId: string; - @Input() displayDeleteButton: boolean; @Input() propertyNameSearchText:string; @Input() searchTerm:string; @Input() readonly:boolean; @Input() isLoading:boolean; + @Input() hasDeclareOption:boolean; + @Input() hidePropertyType:boolean; @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); @Output() selectPropertyRow: EventEmitter<PropertyRowSelectedEvent> = new EventEmitter<PropertyRowSelectedEvent>(); - @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>(); - //@Output() selectInstanceRow: EventEmitter<string> = new EventEmitter<string>(); + @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareOption - - constructor ( private propertiesService:PropertiesService ){ + constructor (private propertiesService:PropertiesService ){ + } + + ngOnInit() { } - propValueChanged = (property) => { - !property.isDeclared && this.valueChanged.emit(property); + this.valueChanged.emit(property); }; // Click on main row (row of propertyFEModel) diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts new file mode 100644 index 0000000000..91f33485a9 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts @@ -0,0 +1,29 @@ +import {NgModule} from "@angular/core"; +import {PropertiesTableComponent} from "./properties-table.component"; +import {DynamicPropertyComponent} from "./dynamic-property/dynamic-property.component"; +import {FormsModule} from "@angular/forms"; +import {UiElementsModule} from "../../ui/ui-elements.module"; +import {CommonModule} from "@angular/common"; +import {HttpModule} from "@angular/http"; +import {FilterChildPropertiesPipe} from "./pipes/filterChildProperties.pipe"; +import {GlobalPipesModule} from "../../../pipes/global-pipes.module"; +import {PropertiesService} from "../../../services/properties.service"; + +@NgModule({ + imports: [ + FormsModule, + HttpModule, + CommonModule, + GlobalPipesModule, + UiElementsModule + ], + declarations: [ + FilterChildPropertiesPipe, + DynamicPropertyComponent, + PropertiesTableComponent + ], + exports: [PropertiesTableComponent], + providers: [FilterChildPropertiesPipe, PropertiesService] +}) +export class PropertyTableModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-reqiurement-or-capability.component.less b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-reqiurement-or-capability.component.less new file mode 100644 index 0000000000..edcb87db3d --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-reqiurement-or-capability.component.less @@ -0,0 +1,77 @@ +@import './../../../../../assets/styles/variables.less'; +@import './../../../../../assets/styles/mixins.less'; +.main-container{ + color: @main_color_m; +} +.select-req-or-cap-span { + float: left; + margin-right: 15px; + font-size: 13px; +} +.select-type-label{ + .m_12_m; + margin-bottom: 2px; +} +.select-type{ + display: flex; + margin-bottom: 10px; + ui-element-dropdown{ + width: 40%; + font-size: 13px; + /deep/ select{ + height: 31px; + } + } +} +.table-and-list-container{ + display: flex; + padding-top: 10px; + .inner-container{ + height: 300px; + overflow-y: auto; + border: @main_color_o solid 1px; + } + .inner-container:not(:last-of-type){ + border-right: none; + } + .requirements-or-capabilities-container { + width: 40%; + &.empty-list{ + background-color: @tlv_color_t; + text-align: center; + &:before{ + content: 'Select "type" above'; + line-height: 298px; + } + } + .req-or-cap-item{ + border-bottom: @main_color_o solid 1px; + padding: 10px; + font-size: 13px; + &:hover:not(.selected){ + background-color:@tlv_color_t; cursor:pointer; + } + } + } + .properties-table-container{ + width: 60%; + display: flex; + &.cap-selected{ + background-color: @tlv_color_t; + border: @main_color_a solid 1px; + -webkit-box-shadow: inset 8px -2px 7px -9px rgba(84,84,84,1); + -moz-box-shadow: inset 8px -2px 7px -9px rgba(84,84,84,1); + box-shadow: inset 8px -2px 7px -9px rgba(84,84,84,1); + } + properties-table{ + margin: 15px; + width: 100%; + } + } +} + +.selected{ + color: @main_color_a; + background-color: @tlv_color_v; + border-left: @main_color_a solid 4px; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.html b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.html new file mode 100644 index 0000000000..bcd33efc30 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.html @@ -0,0 +1,36 @@ +<div class="main-container"> + <span class="select-req-or-cap-span">Select:</span><radio-buttons + [(value)]="selectedReqOrCapOption" + [options]="selectOptions" + [readonly]="disabledSelectReqOrCapOption" + [direction]="'horizontal'" + (valueChange)="onSelectRequirementOrCapability($event)"> + +</radio-buttons> + <label class="select-type-label">Select type:</label> + <div class="select-type"> + <ui-element-dropdown [values]="types" [(value)]="selectedType" (valueChange)="onTypeSelected($event)"></ui-element-dropdown> + </div> + + <div class="table-and-list-container"> + <div class="inner-container requirements-or-capabilities-container" [ngClass]="{'empty-list':!selectedType}"> + <div *ngFor="let item of displayCapReqListFilterByType" + class="req-or-cap-item" + (click)="selectReqOrCapFromList(item)" + [ngClass]="{'selected':selectedReqOrCapModel && (item.uniqueId + item.ownerId + item.name) == (selectedReqOrCapModel.uniqueId + selectedReqOrCapModel.ownerId + selectedReqOrCapModel.name)}"> + {{item.getFullTitle()}} + </div> + </div> + <div class="inner-container properties-table-container" *ngIf="selectedReqOrCapOption == 'Capability'" [ngClass]="{'cap-selected':selectedReqOrCapModel}"> + <properties-table *ngIf="selectedReqOrCapModel" + class="properties-table" + [readonly]="true" + [fePropertiesMap]="capabilityProperties" + [selectedPropertyId]="''" + [hidePropertyType]="true"> + </properties-table> + </div> + + </div> +</div> + diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts new file mode 100644 index 0000000000..ab67dc1850 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts @@ -0,0 +1,182 @@ +/** + * Created by rc2122 on 9/4/2017. + */ +import {Component, EventEmitter, Input, OnInit, Output, SimpleChanges} from '@angular/core'; +import {RadioButtonModel, Match, PropertyModel, InstanceFePropertiesMap, Component as ComponentModel} from "app/models"; +import {Dictionary} from "lodash"; +import {DropdownValue} from "../../ui/form-components/dropdown/ui-element-dropdown.component"; +import {ComponentInstanceServiceNg2} from "../../../services/component-instance-services/component-instance.service"; +import {PropertiesUtils} from "app/ng2/pages/properties-assignment/services/properties.utils"; +import {Requirement} from "../../../../models/requirement"; +import {Capability, RequirementCapabilityModel} from "../../../../models/capability"; + +const REQUIREMENT = 'Requirement'; +const CAPABILITY = 'Capability'; + +@Component({ + selector: 'select-requirement-or-capability', + templateUrl: './select-requirement-or-capability.component.html', + styleUrls: ['./select-reqiurement-or-capability.component.less'] +}) + +export class SelectRequirementOrCapabilityComponent implements OnInit { + + + @Input() optionalRequirementsMap:Dictionary<Requirement[]>; //optional requirement map - key is type, value is array of requirements + @Input() optionalCapabilitiesMap:Dictionary<Capability[]>; //optional capabilities map - key is type, value is array of capabilities + + @Input() selectedReqOrCapOption:string; // the selection value chosen by the user (options: requirement / capability ) + + @Input() currentComponent:ComponentModel; + @Input() componentInstanceId:string; + + @Input() selectedReqOrCapModel:RequirementCapabilityModel; + + @Output() updateSelectedReqOrCap:EventEmitter<RequirementCapabilityModel> = new EventEmitter<RequirementCapabilityModel>(); + @Output() updateCapabilityProperties:EventEmitter<Array<PropertyModel>> = new EventEmitter<Array<PropertyModel>>(); + + types:Array<string> = []; + selectedType:string; + + selectOptions:Array<RadioButtonModel>; + + requirementsTypes:Array<string> = []; + capabilitiesTypes:Array<string> = []; + + disabledSelectReqOrCapOption: boolean; // If we need to disable the option to choose requirement or capability + displayCapReqListFilterByType:RequirementCapabilityModel[]; + + capabilityProperties:InstanceFePropertiesMap; + + constructor(private componentInstanceServiceNg2:ComponentInstanceServiceNg2, + private propertiesUtils:PropertiesUtils) { + this.selectOptions = [new RadioButtonModel(REQUIREMENT, REQUIREMENT), new RadioButtonModel(CAPABILITY, CAPABILITY)]; + } + + private initDefaultReqOrCapSelection = (): void => { + if(this.selectedReqOrCapOption){//for second step + this.disabledSelectReqOrCapOption = true; + } + if (this.selectedReqOrCapModel) {//init when there is selected req or cap + if (this.selectedReqOrCapModel instanceof Capability) { + this.selectedReqOrCapOption = this.selectOptions[1].value; + this.selectedType = this.selectedReqOrCapModel.type; + } else { + this.selectedReqOrCapOption = this.selectOptions[0].value; + this.selectedType = (<Requirement>this.selectedReqOrCapModel).capability; + } + } + if(Object.keys(this.optionalCapabilitiesMap).length === 0) { // If instance don't have capabilities + this.disabledSelectReqOrCapOption = true; + this.selectedReqOrCapOption = this.selectOptions[0].value; + } else if(Object.keys(this.optionalRequirementsMap).length === 0) { // If instance don't have requirements + this.disabledSelectReqOrCapOption = true; + this.selectedReqOrCapOption = this.selectOptions[1].value; + } + this.selectedReqOrCapOption = this.selectedReqOrCapOption || this.selectOptions[1].value; + this.types = this.selectedReqOrCapOption == this.selectOptions[0].value ? this.requirementsTypes : this.capabilitiesTypes; + setTimeout(() => { + if (this.selectedType) { + this.initCapReqListFilterByType(); + } else { + this.setDefaultValueType(); + } + }); + } + + initCapabilityPropertiesTable = ():void => { + if(this.selectedReqOrCapModel instanceof Capability ) { + let selectedCapability = <Capability>this.selectedReqOrCapModel; + if(selectedCapability.properties){ + this.capabilityProperties = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren({ CAPABILITY : selectedCapability.properties}, false); + } + } + } + + ngOnChanges(changes:SimpleChanges) { + if (changes.selectedReqOrCapModel) { + if (this.selectedReqOrCapModel && this.selectedReqOrCapOption === CAPABILITY) { + this.setCapabilityProperties(); + } + } + } + + ngOnInit() { + this.initTypesList(); + this.initDefaultReqOrCapSelection(); + this.initCapabilityPropertiesTable(); + } + + private initTypesList = ():void => { + this.requirementsTypes = _.keys(this.optionalRequirementsMap); + this.requirementsTypes.unshift('All'); + this.capabilitiesTypes = _.keys(this.optionalCapabilitiesMap); + this.capabilitiesTypes.unshift('All'); + } + + private fillInDisplayCapReqListFilterByType = (allOptionalTypesMap:Dictionary<RequirementCapabilityModel[]>):void => { + if(this.selectedType === 'All'){ + this.displayCapReqListFilterByType = []; + _.map(allOptionalTypesMap,(reqOrCapArray:RequirementCapabilityModel[])=>{ + this.displayCapReqListFilterByType = this.displayCapReqListFilterByType.concat(reqOrCapArray); + }) + }else{ + this.displayCapReqListFilterByType = allOptionalTypesMap[this.selectedType]; + } + + // automatically select a *single* requirement or capability: + if (this.displayCapReqListFilterByType.length === 1) { + const selectedReqCap:RequirementCapabilityModel = this.displayCapReqListFilterByType[0]; + this.selectReqOrCapFromList((this.selectedType === CAPABILITY) ? <Capability>selectedReqCap : <Requirement>selectedReqCap); + } + } + + private initCapReqListFilterByType = ():void => { + if (this.selectedReqOrCapOption === CAPABILITY) { + this.fillInDisplayCapReqListFilterByType(this.optionalCapabilitiesMap); + } else { + this.fillInDisplayCapReqListFilterByType(this.optionalRequirementsMap); + } + } + + private onTypeSelected = ():void => { + this.initCapReqListFilterByType(); + if (this.displayCapReqListFilterByType.indexOf(this.selectedReqOrCapModel) === -1) { + this.selectReqOrCapFromList(null); + } + } + + private setDefaultValueType = ():void =>{ + // automatically select a *single* type from the list: + this.selectedType = (this.types.length === 2) ? this.types[1] : this.types[0]; + this.initCapReqListFilterByType(); + } + + private onSelectRequirementOrCapability = ():void => { + this.types = this.selectedReqOrCapOption === REQUIREMENT ? this.requirementsTypes : this.capabilitiesTypes; + this.selectReqOrCapFromList(null); + this.setDefaultValueType(); + } + + private selectReqOrCapFromList = (selected:Requirement|Capability):void => { + if (this.selectedReqOrCapModel !== selected) { + this.selectedReqOrCapModel = selected; + this.updateSelectedReqOrCap.emit(selected); + } + } + + + private setCapabilityProperties = ():void => { + let selectedCapability = <Capability>this.selectedReqOrCapModel; + if (selectedCapability.properties === undefined) { + this.componentInstanceServiceNg2.getInstanceCapabilityProperties(this.currentComponent, this.componentInstanceId, selectedCapability.type, selectedCapability.name) + .subscribe((response:Array<PropertyModel>) => { + this.capabilityProperties = (response && response.length) ? this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren({CAPABILITY : response}, false) : null; + this.updateCapabilityProperties.emit(response); + }, error => {}); + }else{ + this.capabilityProperties = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren({CAPABILITY : selectedCapability.properties}, false); + this.updateCapabilityProperties.emit(selectedCapability.properties); + } + } +} diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.module.ts b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.module.ts new file mode 100644 index 0000000000..cb12dea02a --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.module.ts @@ -0,0 +1,24 @@ +import {NgModule} from "@angular/core"; +import {SelectRequirementOrCapabilityComponent} from "./select-requirement-or-capability.component"; +import {FormsModule} from "@angular/forms"; +import {FormElementsModule} from "../../ui/form-components/form-elements.module"; +import {CommonModule} from "@angular/common"; +import {GlobalPipesModule} from "app/ng2/pipes/global-pipes.module"; +import {PropertyTableModule} from "../properties-table/property-table.module"; + +@NgModule({ + declarations: [ + SelectRequirementOrCapabilityComponent + ], + imports: [ + CommonModule, + FormsModule, + FormElementsModule, + GlobalPipesModule, + PropertyTableModule], + + exports: [SelectRequirementOrCapabilityComponent], + providers: [] +}) +export class SelectRequirementOrCapabilityModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.less b/catalog-ui/src/app/ng2/components/modal/modal.component.less deleted file mode 100644 index c87162afb0..0000000000 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.less +++ /dev/null @@ -1,128 +0,0 @@ -@import '../../../../assets/styles/variables'; -@import '../../../../assets/styles/mixins'; -@import '../../../../assets/styles/sprite-old'; -/deep/ modal { - display: none; - - .custom-modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1000; - overflow: auto; - margin: auto; - display: flex; - align-items: center; - - .ng2-modal-content { - background: #fff; - width: 100%; - box-shadow: 0 5px 15px rgba(0,0,0,.5); - border-radius: 4px; - .ng2-modal-body{ - padding: 20px; - } - - .ng2-modal-header{ - .m_18_m; - font-weight: bold; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - height: 50px; - line-height: 50px; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - text-align: left; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px 20px; - - &.modal-type-standard { - border-bottom: solid 3px @main_color_a; - } - - &.modal-type-error { - border-bottom: solid 3px @func_color_q; - } - - &.modal-type-alert{ - border-bottom: solid 3px @main_color_h; - } - - .title{ - .s_18_m; - -webkit-box-flex: 999; - -ms-flex-positive: 999; - flex-grow: 999; - } - .close-button{ - .sprite; - .sprite.x-btn-black; - cursor: pointer; - } - } - - .ng2-modal-footer{ - background-color: @tlv_color_t; - padding: 17px 30px; - clear: both; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - border-radius: 4px; - button{ - margin: 0 12px 0 6px; - } - } - } - } - - .modal-background { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: #000; - opacity: 0.5; - z-index: 900; - } -} - -.xl { - width: 1200px; -} - -.l { - width: 875px; -} - -.md { - width: 650px; -} - -.sm { - width: 552px; -} - -.xsm { - width: 432px; -} - -body.modal-open { - overflow: hidden; -} diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.less b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.less index e219d49aa4..e219d49aa4 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.less +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts index 246258e44f..53d1590b1c 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts @@ -18,13 +18,13 @@ * ============LICENSE_END========================================================= */ -import { Component, Compiler, EventEmitter, ViewContainerRef, ViewChild, Input, Output, ElementRef, ComponentRef, ComponentFactory, ComponentFactoryResolver } from '@angular/core' -import { UiElementCheckBoxComponent } from './elements-ui/checkbox/ui-element-checkbox.component'; -import { UiElementDropDownComponent, DropdownValue } from './elements-ui/dropdown/ui-element-dropdown.component'; -import { UiElementInputComponent } from './elements-ui/input/ui-element-input.component'; -import {UiElementPopoverInputComponent} from "./elements-ui/popover-input/ui-element-popover-input.component"; +import { Component, Compiler, EventEmitter, ViewContainerRef, ViewChild, Input, Output, ElementRef, ComponentRef, ComponentFactoryResolver } from '@angular/core' import {ValidationConfiguration} from "app/models"; -import {UiElementIntegerInputComponent} from "./elements-ui/integer-input/ui-element-integer-input.component"; +import {UiElementInputComponent} from "../form-components/input/ui-element-input.component"; +import {UiElementPopoverInputComponent} from "../form-components/popover-input/ui-element-popover-input.component"; +import {UiElementIntegerInputComponent} from "../form-components/integer-input/ui-element-integer-input.component"; +import {UiElementDropDownComponent, DropdownValue} from "../form-components/dropdown/ui-element-dropdown.component"; +import {PROPERTY_DATA} from "../../../../utils/constants"; @Component({ selector: 'dynamic-element', @@ -33,7 +33,6 @@ import {UiElementIntegerInputComponent} from "./elements-ui/integer-input/ui-ele entryComponents: [ UiElementInputComponent, UiElementDropDownComponent, - UiElementCheckBoxComponent, UiElementPopoverInputComponent, UiElementIntegerInputComponent ] @@ -72,33 +71,30 @@ export class DynamicElementComponent { } // Factory to create component based on type or peroperty name. - switch(this.type) { - case 'list': - case 'integer': + switch(true) { + case this.path && this.path.toUpperCase().indexOf("SUBNETPOOLID") !== -1: + if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name + let pathArray = this.path.split("#"); + this.name = pathArray[pathArray.length - 2]; + } + this.createComponent(UiElementPopoverInputComponent); + break; + case this.type == 'integer': this.createComponent(UiElementIntegerInputComponent); this.cmpRef.instance.pattern = this.validation.validationPatterns.integer; break; - case 'string': - if (this.path && this.path.toUpperCase().indexOf("SUBNETPOOLID") !== -1) { - if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name - let pathArray = this.path.split("#"); - this.name = pathArray[pathArray.length - 2]; - } - this.createComponent(UiElementPopoverInputComponent); - } - else { - this.createComponent(UiElementInputComponent); - } + case PROPERTY_DATA.SCALAR_TYPES.indexOf(this.type) > -1: + case this.type == 'string': + this.createComponent(UiElementInputComponent); break; - case 'boolean': - //this.createComponent(UiElementCheckBoxComponent); + case this.type == 'boolean': this.createComponent(UiElementDropDownComponent); // Build drop down values let tmp = []; - tmp.push(new DropdownValue('true','TRUE')); - tmp.push(new DropdownValue('false','FALSE')); + tmp.push(new DropdownValue(true,'TRUE')); + tmp.push(new DropdownValue(false,'FALSE')); this.cmpRef.instance.values = tmp; break; default: @@ -131,7 +127,6 @@ export class DynamicElementComponent { } ngAfterContentInit() { - //console.log("DynamicElementComponent: ngAfterContentInit: type: " + this.type + " value: " + this.value); this.isViewInitialized = true; this.updateComponent(); } diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.module.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts index b57020a1d0..50b22505a9 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts @@ -19,32 +19,19 @@ */ import { NgModule } from "@angular/core"; -import { UiElementCheckBoxComponent } from './elements-ui/checkbox/ui-element-checkbox.component'; -import { UiElementDropDownComponent } from './elements-ui/dropdown/ui-element-dropdown.component'; -import { UiElementInputComponent } from './elements-ui/input/ui-element-input.component'; -import { DynamicElementComponent } from "app/ng2/components/dynamic-element/dynamic-element.component"; -import { BrowserModule } from '@angular/platform-browser' -import { FormsModule, ReactiveFormsModule } from '@angular/forms' -import { UiElementPopoverInputComponent } from "./elements-ui/popover-input/ui-element-popover-input.component"; import {PopoverModule} from "../popover/popover.module"; import {TooltipModule} from "../tooltip/tooltip.module"; -import {UiElementIntegerInputComponent} from "./elements-ui/integer-input/ui-element-integer-input.component"; +import {DynamicElementComponent} from "./dynamic-element.component"; +import {FormElementsModule} from "../form-components/form-elements.module"; @NgModule({ declarations: [ DynamicElementComponent, - UiElementInputComponent, - UiElementCheckBoxComponent, - UiElementDropDownComponent, - UiElementPopoverInputComponent, - UiElementIntegerInputComponent ], imports: [ - BrowserModule, - FormsModule, PopoverModule, - ReactiveFormsModule, - TooltipModule + TooltipModule, + FormElementsModule ], exports: [ DynamicElementComponent diff --git a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.html index 872bf90329..872bf90329 100644 --- a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.html diff --git a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.less index 3a28c5fb42..9df2680b6f 100644 --- a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.less @@ -1,5 +1,5 @@ - @import '../../../../assets/styles/tlv-sprite'; -@import '../../../../assets/styles/sprite'; + @import '../../../../../../assets/styles/tlv-sprite'; +@import '../../../../../../assets/styles/sprite'; .checkbox-container { diff --git a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts index c8da016174..c8da016174 100644 --- a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts diff --git a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.module.ts b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.module.ts index 4ac7f2d7cd..4ac7f2d7cd 100644 --- a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.module.ts diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html new file mode 100644 index 0000000000..c6b8384183 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html @@ -0,0 +1,3 @@ +<select name='{{name}}' [(ngModel)]="value" (change)="onSave()" [ngClass]="{'disabled':readonly}" data-tests-id="SelectType"> + <option *ngFor="let ddvalue of values" [ngValue]="ddvalue.label != undefined ? ddvalue.value : ddvalue">{{ddvalue.label||ddvalue}}</option> +</select> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.less index ea3e35140e..ea3e35140e 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts index 970c61531f..5abf32c61b 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts @@ -18,15 +18,14 @@ * ============LICENSE_END========================================================= */ -import { Component, EventEmitter, Output, Input } from '@angular/core' -import { BrowserModule } from '@angular/platform-browser' +import {Component, EventEmitter, Output, Input} from '@angular/core' import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.component'; export class DropdownValue { - value:string; + value:any; label:string; - constructor(value:string,label:string) { + constructor(value:any,label:string) { this.value = value; this.label = label; } @@ -37,16 +36,16 @@ export class DropdownValue { templateUrl: './ui-element-dropdown.component.html', styleUrls: ['./ui-element-dropdown.component.less'], }) -export class UiElementDropDownComponent extends UiElementBase implements UiElementBaseInterface { +export class UiElementDropDownComponent extends UiElementBase implements UiElementBaseInterface { @Input() - values: DropdownValue[]; + values: DropdownValue[]|string[]; constructor() { super(); } onSave() { - this.baseEmitter.emit(JSON.parse(this.value)); + this.baseEmitter.emit(this.value); } } diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts new file mode 100644 index 0000000000..e5bdf1f557 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts @@ -0,0 +1,42 @@ +/** + * Created by rc2122 on 9/5/2017. + */ +import {NgModule} from "@angular/core"; +import {BrowserModule} from "@angular/platform-browser"; +import {FormsModule, ReactiveFormsModule} from "@angular/forms"; +import {UiElementPopoverInputComponent} from "./popover-input/ui-element-popover-input.component"; +import {UiElementIntegerInputComponent} from "./integer-input/ui-element-integer-input.component"; +import {UiElementInputComponent} from "./input/ui-element-input.component"; +import {UiElementDropDownComponent} from "./dropdown/ui-element-dropdown.component"; +import {UiElementBase} from "./ui-element-base.component"; +import {CheckboxModule} from "./checkbox/checkbox.module"; +import {RadioButtonComponent} from "./radio-buttons/radio-buttons.component"; +import {PopoverModule} from "../popover/popover.module"; +import {TooltipModule} from "../tooltip/tooltip.module"; + + +@NgModule({ + imports: [ + BrowserModule, + FormsModule, + PopoverModule, + ReactiveFormsModule, + TooltipModule, + CheckboxModule], + + declarations: [UiElementDropDownComponent, + UiElementInputComponent, + UiElementIntegerInputComponent, + UiElementPopoverInputComponent, + UiElementBase, + RadioButtonComponent], + + exports: [UiElementDropDownComponent, + UiElementInputComponent, + UiElementIntegerInputComponent, + UiElementPopoverInputComponent, + RadioButtonComponent, + TooltipModule, + CheckboxModule] +}) +export class FormElementsModule { }
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html index 814ebfd28b..b7d7c859c7 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html @@ -1,6 +1,6 @@ <input class="value-input" - [ngClass]="{'error': control.invalid}" + [ngClass]="{'error': control.invalid, 'disabled':readonly}" type="text" [name]="name" [(ngModel)]="value" @@ -11,5 +11,4 @@ [formControl]="control" tooltip="{{value}}" [readonly]="readonly" - [ngClass]="{'disabled':readonly}" /> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.less index d320c7ff8b..d320c7ff8b 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts index fb3b3db859..fb3b3db859 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html index e5518d453f..9fbc9e1094 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html @@ -1,6 +1,6 @@ <input class="value-input" - [ngClass]="{'error': control.invalid}" + [ngClass]="{'error': control.invalid, 'disabled':readonly}" type="text" [name]="name" [(ngModel)]="value" @@ -11,5 +11,4 @@ [formControl]="control" tooltip="{{value}}" [readonly]="readonly" - [ngClass]="{'disabled':readonly}" /> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.less index 8073c3858e..8073c3858e 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts index 3339b605ca..1667f4393d 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts @@ -30,7 +30,7 @@ import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.comp export class UiElementIntegerInputComponent extends UiElementBase implements UiElementBaseInterface { constructor() { super(); - this.pattern = this.validation.validationPatterns.comment; + //this.pattern = this.validation.validationPatterns.comment; } onSave() { diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.html index 3bd51b4e36..3bd51b4e36 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.html diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.less index 5be443f7b6..5be443f7b6 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts index 67eb8822b4..61688df3f0 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts @@ -19,10 +19,9 @@ */ import {Component, ViewChild, ElementRef, Input} from '@angular/core'; -import {UiElementBase, UiElementBaseInterface} from "../ui-element-base.component"; import {ButtonsModelMap, ButtonModel} from "app/models"; -import { PopoverContentComponent } from "app/ng2/components/popover/popover-content.component" -import { PopoverComponent } from "app/ng2/components/popover/popover.component" +import {PopoverContentComponent} from "../../popover/popover-content.component"; +import {UiElementBase, UiElementBaseInterface} from "../ui-element-base.component"; @Component({ selector: 'ui-element-popover-input', diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-button.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-button.component.less new file mode 100644 index 0000000000..b929486b10 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-button.component.less @@ -0,0 +1,42 @@ +@import './../../../../../../assets/styles/variables.less'; +.radio-buttons-container{ + display: flex; + &.vertical{ + flex-direction: column; + } + &.horizontal{ + flex-direction: row; + } +} +.radio-button { + margin: 0 10px 10px 0; + display: flex; +} + +input[type=radio] { + width:0; + height:0; + display:none; + &[disabled] ~ .radio-button { + + } +} + +.shown-radio-button{ + border: @main_color_n solid 1px; + height: 14px; + width: 14px; + border-radius: 50%; + padding: 1px; + margin: auto 5px; + .selected{ + background-color: @main_color_a; + height: 100%; + width: 100%; + border-radius: 50%; + } +} +span{ + margin: auto 0; + color: @func_color_s; +} diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.html new file mode 100644 index 0000000000..6c927301db --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.html @@ -0,0 +1,8 @@ +<div class="radio-buttons-container {{direction}}"> + <div *ngFor="let option of options" class="radio-button" [ngClass]="{'disabled':readonly}"> + <input type="radio" [(ngModel)]="value" name="{{fieldName}}" value="{{option.value}}" [disabled]="readonly"/> + <div class="shown-radio-button" (click)="!readonly && select(option.value)"><div *ngIf="value==option.value" class="selected"></div></div> + <span>{{option.key}}</span> + </div> +</div> + diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts new file mode 100644 index 0000000000..0f80e2ad44 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts @@ -0,0 +1,29 @@ +/** + * Created by rc2122 on 9/4/2017. + */ +import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; +import { RadioButtonModel } from 'app/models' +import {UiElementBaseInterface, UiElementBase} from "../ui-element-base.component"; + +@Component({ + selector: 'radio-buttons', + templateUrl: './radio-buttons.component.html', + styleUrls: ['./radio-button.component.less'] +}) +export class RadioButtonComponent extends UiElementBase implements UiElementBaseInterface { + + onSave() { + this.baseEmitter.emit(this.value); + } + + @Input() options:Array<RadioButtonModel>; + @Input() readonly:boolean; + @Input() direction:string = 'vertical'; //get 'horizontal' | 'vertical' + value:any; + + select(value:any) { + this.value = value; + this.baseEmitter.emit(this.value); + } +} + diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/ui-element-base.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts index 4bc35e814a..ae2013ff70 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/ui-element-base.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts @@ -41,11 +41,11 @@ export class UiElementBase { this.value = value; } - protected name: string; - protected type: string; - protected value: any; - protected pattern: any; - protected readonly:boolean; + @Input() name: string; + @Input() type: string; + @Input() value: any; + @Input() pattern: any; + @Input() readonly:boolean; constructor() { //this.control = new FormControl('', [Validators.required]); diff --git a/catalog-ui/src/app/ng2/components/loader/loader.component.html b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html index a62aa114d9..a62aa114d9 100644 --- a/catalog-ui/src/app/ng2/components/loader/loader.component.html +++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html diff --git a/catalog-ui/src/app/ng2/components/loader/loader.component.less b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.less index ddb9915176..006c3bfa43 100644 --- a/catalog-ui/src/app/ng2/components/loader/loader.component.less +++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.less @@ -1,4 +1,4 @@ -@import '../../../../assets/styles/variables'; +@import '../../../../../assets/styles/variables'; .tlv-loader-back { background-color: @main_color_p; position: fixed; diff --git a/catalog-ui/src/app/ng2/components/loader/loader.component.ts b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts index f66aa551e2..f66aa551e2 100644 --- a/catalog-ui/src/app/ng2/components/loader/loader.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.html b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.html new file mode 100644 index 0000000000..54640c9414 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.html @@ -0,0 +1,3 @@ +<div class="w-sdc-menu-item" [ngClass]="styleClass" (click)="performAction()"> + <ng-content></ng-content> +</div> diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.less b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.less new file mode 100644 index 0000000000..ceb4409144 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.less @@ -0,0 +1,13 @@ +@import "../../../../../assets/styles/variables"; + +.w-sdc-menu-item { + font-size: 14px; + line-height: 14px; + color: @main_color_m; + padding: 3px 6px; + + &:hover { + cursor: pointer; + background-color: @main_color_c; + } +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts index f73afd42c7..8b2006634e 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts @@ -7,9 +7,9 @@ * 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. @@ -18,30 +18,27 @@ * ============LICENSE_END========================================================= */ -import { Component, ViewChild, ElementRef, ContentChildren, Input } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser' -import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.component'; +import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ - selector: 'ui-element-checkbox', - templateUrl: './ui-element-checkbox.component.html', - styleUrls: ['./ui-element-checkbox.component.less'], + selector: 'menu-item', + templateUrl: './menu-item.component.html', + styleUrls:['./menu-item.component.less'] }) -export class UiElementCheckBoxComponent extends UiElementBase implements UiElementBaseInterface { +export class MenuItemComponent { + @Input() action:Function; + @Input() styleClass:any; - constructor() { - super(); - } + public parentMenu:any; - ngAfterContentInit() { - // Convert the value to boolean (instanceOf does not work, the type is undefined). - if (this.value==='true' || this.value==='false') { - this.value = this.value==='true'?true:false; + constructor() { } - } - onSave() { - this.baseEmitter.emit(this.value); - } + performAction() { + this.action(); + if (this.parentMenu && typeof(this.parentMenu.close) === 'function') { + this.parentMenu.close(); + } + } } diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.html b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.html new file mode 100644 index 0000000000..98c4d26fdd --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.html @@ -0,0 +1,9 @@ +<div + class="w-sdc-menu-list" + *ngIf="isOpen" + [ngClass]="styleClass" + [ngStyle]="{'left': position?.x || 0, 'top': position?.y || 0}"> + + <ng-content></ng-content> + +</div> diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.less b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.less new file mode 100644 index 0000000000..1b45ea775c --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.less @@ -0,0 +1,13 @@ +.w-sdc-menu-list { + position: fixed; + z-index: 100; + + border-style: solid; + border-width: 1px; + border-color: #d8d8d8; + box-sizing: border-box; + background-color: #ffffff; + box-shadow: 0px 2px 2px 0px rgba(24, 24, 25, 0.1); + width: 91px; + padding: 6px 0; +} diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts new file mode 100644 index 0000000000..290c8d06af --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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, Input, ContentChildren, SimpleChanges, QueryList } from '@angular/core'; +import { MenuItemComponent } from "./menu-item.component"; +import { Point } from "app/models"; + +@Component({ + selector: 'menu-list', + templateUrl: './menu-list.component.html', + styleUrls:['./menu-list.component.less'] +}) +export class MenuListComponent { + @Input('open') inputOpen:boolean = false; + @Input('position') inputPosition:Point = new Point(); + @Input() styleClass:any; + + @ContentChildren(MenuItemComponent) menuItems:QueryList<MenuItemComponent>; + + private position:Point; + private isOpen:boolean = false; + + constructor() { + } + + ngOnChanges(changes:SimpleChanges) { + if (changes.inputOpen) { + (changes.inputOpen.currentValue) ? this.open() : this.close(); + } + if (changes.inputPosition) { + this.changePosition(changes.inputPosition.currentValue); + } + } + + ngAfterContentInit() { + this.menuItems.forEach((c) => c.parentMenu = this); + this.menuItems.changes.subscribe((list) => { + list.forEach((c) => c.parentMenu = this); + }); + } + + open(): void { + this.isOpen = true; + } + + close(): void { + this.isOpen = false; + } + + changePosition(position:Point) { + this.position = position; + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.module.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.module.ts new file mode 100644 index 0000000000..fdbbf59f48 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.module.ts @@ -0,0 +1,27 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from '@angular/common'; +import { MenuListComponent } from "./menu-list.component"; +import { MenuItemComponent } from "./menu-item.component"; + +export { + MenuListComponent, + MenuItemComponent +}; + +@NgModule({ + declarations: [ + MenuListComponent, + MenuItemComponent + ], + imports: [CommonModule], + exports: [ + MenuListComponent, + MenuItemComponent + ], + entryComponents: [ //need to add anything that will be dynamically created + MenuListComponent, + MenuItemComponent + ] +}) +export class MenuListModule { +} diff --git a/catalog-ui/src/app/ng2/components/modal/error-message/error-message.component.html b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.html index 433bd4fd6f..433bd4fd6f 100644 --- a/catalog-ui/src/app/ng2/components/modal/error-message/error-message.component.html +++ b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.html diff --git a/catalog-ui/src/app/ng2/components/modal/error-message/error-message.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.ts index c0d6673412..c0d6673412 100644 --- a/catalog-ui/src/app/ng2/components/modal/error-message/error-message.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.ts diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.html b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html index d843867cdb..9a0fdf6bf4 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.html +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html @@ -13,6 +13,7 @@ <button *ngFor="let button of input.buttons" class="tlv-btn {{button.cssClass}}" [disabled] = "button.getDisabled && button.getDisabled()" + [attr.data-tests-id] = "button.text" (click) = "button.callback()">{{button.text}}</button> </div> </div> diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less new file mode 100644 index 0000000000..fac1ae74a8 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less @@ -0,0 +1,129 @@ +@import '../../../../../assets/styles/variables'; +@import '../../../../../assets/styles/mixins'; +@import '../../../../../assets/styles/sprite-old'; +/deep/ modal { + display: none; +} + +.custom-modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 15007; + overflow: auto; + margin: auto; + display: flex; + align-items: center; + + .ng2-modal-content { + background: #fff; + width: 100%; + box-shadow: 0 5px 15px rgba(0,0,0,.5); + border-radius: 4px; + .ng2-modal-body{ + padding: 20px; + } + + .ng2-modal-header{ + .m_18_r; + font-weight: bold; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + height: 50px; + line-height: 50px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + text-align: left; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin: 0px 20px; + + &.modal-type-standard { + border-bottom: solid 3px @main_color_a; + } + + &.modal-type-error { + border-bottom: solid 3px @func_color_q; + } + + &.modal-type-alert{ + border-bottom: solid 3px @main_color_h; + } + + .title{ + .s_18_r; + -webkit-box-flex: 999; + -ms-flex-positive: 999; + flex-grow: 999; + } + .close-button{ + .sprite; + .sprite.x-btn-black; + cursor: pointer; + } + } + + .ng2-modal-footer{ + background-color: @tlv_color_t; + padding: 17px 30px; + clear: both; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + border-radius: 4px; + button{ + margin: 0 12px 0 6px; + } + } + } +} + +.modal-background { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: #000; + opacity: 0.5; + z-index: 900; +} + + +.xl { + width: 1200px; +} + +.l { + width: 875px; +} + +.md { + width: 650px; +} + +.sm { + width: 552px; +} + +.xsm { + width: 432px; +} + +body.modal-open { + overflow: hidden; +} diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts index 89db8d1140..89db8d1140 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts diff --git a/catalog-ui/src/app/ng2/components/modal/modal.module.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts index 892f6993dd..c38e60194b 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts @@ -1,8 +1,8 @@ import { NgModule } from "@angular/core"; import { CommonModule } from '@angular/common'; import { ModalService } from 'app/ng2/services/modal.service'; -import { ModalComponent } from "app/ng2/components/modal/modal.component"; import { ErrorMessageComponent } from "./error-message/error-message.component"; +import {ModalComponent} from "./modal.component"; @NgModule({ declarations: [ @@ -10,7 +10,7 @@ import { ErrorMessageComponent } from "./error-message/error-message.component"; ErrorMessageComponent ], imports: [CommonModule], - exports: [], + exports: [ModalComponent, ErrorMessageComponent], entryComponents: [ //need to add anything that will be dynamically created ModalComponent, ErrorMessageComponent diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component.ts new file mode 100644 index 0000000000..0c1669ec4b --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component.ts @@ -0,0 +1,10 @@ +/** + * Created by rc2122 on 9/27/2017. + */ +import {Component, Input} from "@angular/core"; +@Component({ +}) +export class WizardHeaderBaseComponent { + + @Input() currentStepIndex:number; +} diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.html b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.html new file mode 100644 index 0000000000..9884b233ac --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.html @@ -0,0 +1,57 @@ +<div class="custom-modal {{input.size}}"> + <div class="ng2-modal-content w-sdc-classic-top-line-modal"> + <div class="ng2-modal-header modal-type-{{input.type}}"> + <span class="title">{{ input.title }}</span> + <span class="close-button" (click)="close()"></span> + </div> + <div class="ng2-modal-body" > + <div class="multi-steps-wizard-component"> + <header> + <div class="steps-header"> + <div *ngFor="let step of steps; let i = index" class="step-title" [ngClass]="{'active':i == currentStepIndex}"> + <div class="title-text">{{step.title}}</div> + <div class="line"> + <div class="inner-line" [@displayLineAnimation]="i <= currentStepIndex && i!=0" [hidden]="!i || i > currentStepIndex"></div> + </div> + <div class="circle" [ngClass]="{'full-circle': i < currentStepIndex}"></div> + </div> + </div> + <div class="dynamic-header-container"> + <div #dynamicHeaderContainer></div> + </div> + </header> + <div #dynamicContentContainer></div> + </div> + </div> + + <div class="ng2-modal-footer"> + <button *ngFor="let button of input.buttons" + class="tlv-btn {{button.cssClass}}" + [disabled] = "button.getDisabled && button.getDisabled()" + (click) = "button.callback()">{{button.text}}</button> + <div class="navigation-buttons"> + <button (click)="prevStep()" + class="navigation-button tlv-btn outline blue" + [disabled]="dynamicContent.instance.preventBack()"> + <div class="navigation-icon sprite-new blue-arrow-back"></div> + Back + </button> + <button (click)="nextStep()" + *ngIf="currentStepIndex < (steps.length - 1)" + [disabled]="dynamicContent.instance.preventNext()" + class="navigation-button tlv-btn blue"> + Next + <div class="navigation-icon sprite-new white-arrow-next"></div> + </button> + <button (click)="callback();modalService.closeCurrentModal();" + *ngIf="currentStepIndex == (steps.length - 1)" + [disabled]="dynamicContent.instance.preventNext()" + class="tlv-btn blue"> + Finish + </button> + </div> + + </div> + </div> +</div> +<div class="modal-background"></div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.less b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.less new file mode 100644 index 0000000000..3a2168aeb0 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.less @@ -0,0 +1,90 @@ +@import './../../../../../assets/styles/variables.less'; + +@circle_size: 13px; + +.custom-modal{ + font-family: @font-opensans-regular; +} + +/deep/ multi-steps-wizard { + display: none; +} + +.ng2-modal-header{ + border: none !important; +} + +.ng2-modal-body{ + padding-top: 0 !important; +} + +header{ + margin-bottom: 10px; + .dynamic-header-container{ + position: relative; + top: -9px; + } + .steps-header{ + display: flex; + .step-title{ + flex: 1; + .title-text{ + width: 100%; + text-align: center; + line-height: 40px; + background-color: @tlv_color_u; + font-size: 13px; + } + .line{ + width: calc(~'100% - @{circle_size}'); + position: relative; + left: calc(~'(100% - @{circle_size})/2 * (-1)'); + float: left; + height: 2px; + .inner-line{ + background-color: @main_color_a; + height: 100%; + } + } + .circle{ + margin:0 auto; + border: @main_color_o solid 1px; + height: @circle_size; + width: @circle_size; + border-radius: 50%; + position: relative; + top: -@circle_size/2; + background-color: @main_color_p; + z-index: 1; + } + .full-circle{ + border-color: @main_color_a; + background-color: @main_color_a; + } + &.active{ + color: @main_color_a; + font-family: @font-opensans-medium; + .circle{ + border-color: @main_color_a; + } + } + } + } +} + +.navigation-buttons{ + padding-left: 6px; + border-left: 1px solid @main_color_a; + .navigation-button{ + padding: 0 8px; + .navigation-icon{ + margin: 3px 0; + &.blue-arrow-back{ + float: left; + } + &.white-arrow-next{ + float: right; + } + } + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts new file mode 100644 index 0000000000..9219a30738 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts @@ -0,0 +1,78 @@ +/** + * Created by rc2122 on 8/15/2017. + */ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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, ElementRef, forwardRef, Inject, Input, trigger, state, style, + transition, animate, ViewChild, ViewContainerRef, ComponentRef +} from "@angular/core"; +import {StepModel} from "app/models"; +import {ModalService} from "../../../services/modal.service"; +import {ModalComponent} from "../modal/modal.component"; +import {WizardHeaderBaseComponent} from "./multi-steps-wizard-header-base.component"; + + +@Component({ + selector: 'multi-steps-wizard', + templateUrl: './multi-steps-wizard.component.html', + styleUrls: ['./../modal/modal.component.less','./multi-steps-wizard.component.less'], + animations: [ + trigger('displayLineAnimation', [ + state('true', style({ + width: '100%', + })), + state('false', style({ + width:'0px', + })), + transition('* => *', animate('500ms')), + ]), + ], +}) +export class MultiStepsWizardComponent extends ModalComponent { + + @Input() steps:Array<StepModel>; + @Input() callback: Function; + @Input() data:any; + @Input() dynamicHeader: ComponentRef<WizardHeaderBaseComponent>; + + @ViewChild('dynamicHeaderContainer', { read: ViewContainerRef }) dynamicHeaderContainer: ViewContainerRef; + constructor(@Inject(forwardRef(() => ModalService)) public modalService: ModalService, el: ElementRef ) { + super(el); + } + + private currentStepIndex:number = 0; + + nextStep = ():void => { + if(this.currentStepIndex + 1 < this.steps.length){ + this.currentStepIndex++; + this.modalService.addDynamicContentToModal(this.modalService.currentModal, this.steps[this.currentStepIndex].component); + this.dynamicHeader.instance.currentStepIndex = this.currentStepIndex; + } + } + + prevStep = ():void => { + if(this.currentStepIndex > 0){ + this.currentStepIndex--; + this.modalService.addDynamicContentToModal(this.modalService.currentModal, this.steps[this.currentStepIndex].component); + this.dynamicHeader.instance.currentStepIndex = this.currentStepIndex; + } + } +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts new file mode 100644 index 0000000000..3db217d282 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts @@ -0,0 +1,22 @@ +/** + * Created by rc2122 on 8/15/2017. + */ +import { NgModule } from "@angular/core"; +import {MultiStepsWizardComponent} from "./multi-steps-wizard.component"; +import {CommonModule} from "@angular/common"; +import {ConnectionWizardModule} from "../../../pages/connection-wizard/connection-wizard.module"; + +@NgModule({ + declarations: [ + MultiStepsWizardComponent + ], + imports: [CommonModule + ], + exports: [], + entryComponents: [ + MultiStepsWizardComponent + ], + providers: [] +}) +export class MultiStepsWizardModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar-routes.config.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar-routes.config.ts index ac58cbd063..ac58cbd063 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar-routes.config.ts +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar-routes.config.ts diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.html b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.html index d783be4c27..d783be4c27 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.html +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.html diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.less b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.less index 3e5165b798..3e5165b798 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.less +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.less diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.ts index 68a26c4780..68a26c4780 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.ts diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.metadata.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.metadata.ts index 71cc3cb59f..71cc3cb59f 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.metadata.ts +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.metadata.ts diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.module.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.module.ts index 4a754dfe99..4a754dfe99 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.module.ts diff --git a/catalog-ui/src/app/ng2/components/popover/popover-content.component.html b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html index 6d76f0ad06..6d76f0ad06 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover-content.component.html +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html diff --git a/catalog-ui/src/app/ng2/components/popover/popover-content.component.less b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.less index 04cdd3914b..fbdec0b16b 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover-content.component.less +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.less @@ -1,6 +1,6 @@ -@import '../../../../assets/styles/variables'; -@import '../../../../assets/styles/mixins'; -@import '../../../../assets/styles/sprite-old'; +@import '../../../../../assets/styles/variables'; +@import '../../../../../assets/styles/mixins'; +@import '../../../../../assets/styles/sprite-old'; .popover .virtual-area { height: 11px; width: 100%; diff --git a/catalog-ui/src/app/ng2/components/popover/popover-content.component.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts index 6eb36287d0..6eb36287d0 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover-content.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts diff --git a/catalog-ui/src/app/ng2/components/popover/popover.component.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover.component.ts index e976bc7bf2..e976bc7bf2 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover.component.ts diff --git a/catalog-ui/src/app/ng2/components/popover/popover.module.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover.module.ts index a9605c17b6..d8cacc1696 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover.module.ts @@ -32,8 +32,6 @@ import {PopoverContentComponent} from "./popover-content.component"; PopoverContentComponent ], imports: [ - // PopoverComponent, - // PopoverContentComponent CommonModule ], exports: [ diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html index 36629594b0..36629594b0 100644 --- a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less index cfeb8d3b01..751fceec35 100644 --- a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less @@ -30,8 +30,7 @@ } .search-bar-button { - //background: url('../../../../assets/styles/svg/source/search-magnify.svg') no-repeat 50%; - background: url('../../../../assets/styles/images/sprites/sprite-global.png') no-repeat -206px -1275px; + background: url('../../../../../assets/styles/images/sprites/sprite-global.png') no-repeat -206px -1275px; background-color: rgba(234, 234, 234, 0.88); width: 30px; height: 30px; diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.ts index 08bdf2030f..08bdf2030f 100644 --- a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.ts diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html index c9769ba5ae..c9769ba5ae 100644 --- a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less index 92b054cd85..f1830846d3 100644 --- a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less @@ -1,5 +1,4 @@ - -.search-with-autocomplete-container{ +.search-with-autocomplete-container{ &.autocomplete-visible { .search-bar-input { diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.ts index ced056d1fc..ced056d1fc 100644 --- a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.ts diff --git a/catalog-ui/src/app/ng2/shared/tabs/tab/tab.component.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tab/tab.component.ts index bad7b80a51..bad7b80a51 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tab/tab.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tab/tab.component.ts diff --git a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.html b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.html index 3e263a3862..57cf5d46c9 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.html +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.html @@ -1,5 +1,5 @@ <div class="tabs {{tabStyle}}"> - <div class="tab" *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active"> + <div class="tab" *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active" [attr.data-tests-id]="tab.title"> {{tab.title}} <div class="tab-indication" *ngIf="tab.indication" [@indicatorAnimation]="tab.indication">{{tab.indication}}</div> </div> diff --git a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.less b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.less index 6f9e57aaf2..f7b18b1cc8 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.less +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.less @@ -1,4 +1,4 @@ -@import '../../../../assets/styles/variables'; +@import '../../../../../assets/styles/variables'; tab { height: 100%; @@ -20,6 +20,7 @@ tab { flex: 1; width:100%; overflow-y:hidden; + overflow-x:hidden; } .tab-content { diff --git a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts index 21d2bbad43..21d2bbad43 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts diff --git a/catalog-ui/src/app/ng2/shared/tabs/tabs.module.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.module.ts index 6bf19d4099..1300c41a90 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tabs.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.module.ts @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import { Component, NgModule } from '@angular/core' +import { NgModule } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' import { Tabs } from './tabs.component'; diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.html b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.html index 1fbf45e39f..1fbf45e39f 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.html +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.html diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.less b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.less index 1ff496f840..1ff496f840 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.less +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.less diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.ts index 4dcb64c499..4dcb64c499 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.ts diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip.component.ts b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.component.ts index 79d35c6e0e..79d35c6e0e 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.component.ts diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip.module.ts b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.module.ts index 84a3987081..24478cd716 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.module.ts @@ -29,7 +29,6 @@ import {CommonModule} from "@angular/common"; TooltipContentComponent, ], imports: [ - CommonModule ], exports: [ TooltipComponent, diff --git a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts new file mode 100644 index 0000000000..526096524c --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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 { NavbarModule } from "./navbar/navbar.module"; +import {DynamicElementModule} from "./dynamic-element/dynamic-element.module"; +import {FormElementsModule} from "./form-components/form-elements.module"; +import {LoaderComponent} from "./loader/loader.component"; +import {ModalModule} from "./modal/modal.module"; +import {PopoverModule} from "./popover/popover.module"; +import {SearchBarComponent} from "./search-bar/search-bar.component"; +import {SearchWithAutoCompleteComponent} from "./search-with-autocomplete/search-with-autocomplete.component"; +import {TabModule} from "./tabs/tabs.module"; +import {TooltipModule} from "./tooltip/tooltip.module"; +import {CommonModule} from "@angular/common"; +import {FormsModule} from "@angular/forms"; +import {BrowserModule} from "@angular/platform-browser"; +import {MultiStepsWizardModule} from "./multi-steps-wizard/multi-steps-wizard.module"; +import {MenuListModule} from "./menu/menu-list.module"; +import {MenuListNg2Module} from "../downgrade-wrappers/menu-list-ng2/menu-list-ng2.module"; + +@NgModule({ + declarations: [ + LoaderComponent, + SearchBarComponent, + SearchWithAutoCompleteComponent + ], + + imports: [ + BrowserModule, + FormsModule, + CommonModule, + DynamicElementModule, + NavbarModule, + FormElementsModule, + ModalModule, + PopoverModule, + TabModule, + TooltipModule, + MultiStepsWizardModule, + MenuListModule, + MenuListNg2Module + ], + exports: [ + LoaderComponent, + MultiStepsWizardModule, + SearchBarComponent, + SearchWithAutoCompleteComponent, + DynamicElementModule, + NavbarModule, + FormElementsModule, + ModalModule, + PopoverModule, + TabModule, + TooltipModule, + MenuListModule, + MenuListNg2Module + ], + + entryComponents: [SearchWithAutoCompleteComponent] +}) + +export class UiElementsModule {} diff --git a/catalog-ui/src/app/ng2/config/sdc-config.config.factory.ts b/catalog-ui/src/app/ng2/config/sdc-config.config.factory.ts new file mode 100644 index 0000000000..b0fa17d3b6 --- /dev/null +++ b/catalog-ui/src/app/ng2/config/sdc-config.config.factory.ts @@ -0,0 +1,17 @@ +declare const __ENV__:string; + +export interface ISdcConfig { + [index:string]: any +} + +export function getSdcConfig() : ISdcConfig { + let sdcConfig:ISdcConfig = {}; + + if (__ENV__==='prod') { + sdcConfig = require('./../../../../configurations/prod.js'); + } else { + sdcConfig = require('./../../../../configurations/dev.js'); + } + + return sdcConfig; +} diff --git a/catalog-ui/src/app/ng2/config/sdc-config.config.ts b/catalog-ui/src/app/ng2/config/sdc-config.config.ts new file mode 100644 index 0000000000..197cc8b14b --- /dev/null +++ b/catalog-ui/src/app/ng2/config/sdc-config.config.ts @@ -0,0 +1,11 @@ +import {Provider, OpaqueToken} from "@angular/core"; +import {getSdcConfig, ISdcConfig} from "./sdc-config.config.factory"; + +export { ISdcConfig }; + +export const SdcConfigToken = new OpaqueToken('SdcConfigToken'); + +export const SdcConfig:Provider = { + provide: SdcConfigToken, + useFactory: getSdcConfig +}; diff --git a/catalog-ui/src/app/ng2/config/translation.service.config.factory.ts b/catalog-ui/src/app/ng2/config/translation.service.config.factory.ts new file mode 100644 index 0000000000..c435e45def --- /dev/null +++ b/catalog-ui/src/app/ng2/config/translation.service.config.factory.ts @@ -0,0 +1,13 @@ +import { ITranslateServiceConfig } from "../shared/translator/translate.service.config"; + +declare const __ENV__:string; + +export function getTranslationServiceConfig() : ITranslateServiceConfig { + const pathPrefix = (__ENV__ === 'prod') ? 'sdc1/' : ''; + return { + filePrefix: pathPrefix + 'assets/languages/', + fileSuffix: '.json', + allowedLanguages: ['en_US'], + defaultLanguage: 'en_US' + }; +} diff --git a/catalog-ui/src/app/ng2/config/translation.service.config.ts b/catalog-ui/src/app/ng2/config/translation.service.config.ts new file mode 100644 index 0000000000..9c2df7a098 --- /dev/null +++ b/catalog-ui/src/app/ng2/config/translation.service.config.ts @@ -0,0 +1,8 @@ +import { Provider } from "@angular/core"; +import { TranslateServiceConfigToken } from "../shared/translator/translate.service.config"; +import { getTranslationServiceConfig } from "./translation.service.config.factory"; + +export const TranslationServiceConfig:Provider = { + provide: TranslateServiceConfigToken, + useFactory: getTranslationServiceConfig +}; diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.html new file mode 100644 index 0000000000..02e7694eb0 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.html @@ -0,0 +1,4 @@ +<div> + <connection-wizard-header currentStepIndex="2"></connection-wizard-header> + <properties-step></properties-step> +</div> diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.less b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.less new file mode 100644 index 0000000000..07f9aa2135 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.less @@ -0,0 +1,4 @@ +connection-wizard-header { + display: block; + margin-bottom: 15px; +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.ts new file mode 100644 index 0000000000..5abb879013 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.ts @@ -0,0 +1,10 @@ +import {Component} from "@angular/core"; + + +@Component({ + selector: 'connection-properties-view', + templateUrl: './connection-properties-view.component.html', + styleUrls:['./connection-properties-view.component.less'] +}) +export class ConnectionPropertiesViewComponent { +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.html new file mode 100644 index 0000000000..369ab50cad --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.html @@ -0,0 +1,36 @@ +<div class="header-main-container"> + <div class="inner-container"> + <div class="node from-node" [ngClass]="{'selected':currentStepIndex == 0}"> + <div class="text"> + <div class="node-name"> + {{connectWizardService.connectRelationModel.fromNode.componentInstance.name}} + </div> + <div class="selected-req-or-cap" [ngClass]="{'selected': currentStepIndex == 2 && !connectWizardService.selectedMatch.isFromTo}"> + {{getSelectedReqOrCapName(true)}} + </div> + </div> + <div class="icon"> + <div class="small medium {{connectWizardService.connectRelationModel.fromNode.componentInstance.iconSprite}} {{connectWizardService.connectRelationModel.fromNode.componentInstance.icon}}"> + </div> + </div> + </div> + <div class="connection"> + + </div> + <div class="node to-node" [ngClass]="{'selected':currentStepIndex == 1}"> + <div class="icon"> + <div class="small medium {{connectWizardService.connectRelationModel.toNode.componentInstance.iconSprite}} {{connectWizardService.connectRelationModel.toNode.componentInstance.icon}}"> + </div> + </div> + + <div class="text"> + <div class="node-name"> + {{connectWizardService.connectRelationModel.toNode.componentInstance.name}} + </div> + <div class="selected-req-or-cap" [ngClass]="{'selected': currentStepIndex == 2 && connectWizardService.selectedMatch.isFromTo}"> + {{getSelectedReqOrCapName(false)}} + </div> + </div> + </div> + </div> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.less b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.less new file mode 100644 index 0000000000..72fa6e813f --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.less @@ -0,0 +1,53 @@ +@import '../../../../../assets/styles/sprite-proxy-services-icons'; +@import '../../../../../assets/styles/variables'; +.header-main-container{ + background-color: #f8f8f8; + width: 100%; + height: 100px; + display: flex; + .inner-container{ + margin: 0 auto; + display: flex; + } +} +.selected { + color: @main_color_a; +} +.node{ + display: flex; + &.from-node{ + text-align: right; + } + &.to-node{ + text-align: left; + } + &.selected{ + .icon{ + border: solid 3px @main_color_a; + padding: 4px; + border-radius: 50%; + background-color: @main_color_p; + } + } + .icon{ + margin: auto 0; + display: flex; + } + .text{ + font-family: @font-opensans-medium; + margin: auto 10px; + min-width: 450px; + .node-name{ + font-size: 11px; + } + .selected-req-or-cap{ + font-size: 14px; + } + } +} +.connection{ + width: 67px; + height: 0px; + border-bottom: dashed 2px #979797; + margin: auto 0; +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts new file mode 100644 index 0000000000..f5bc3b7ca4 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts @@ -0,0 +1,37 @@ +/** + * Created by rc2122 on 9/27/2017. + */ +import {Component, Inject, forwardRef} from "@angular/core"; +import {ConnectionWizardService} from "../connection-wizard.service"; +import {WizardHeaderBaseComponent} from "app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component"; + +@Component({ + selector: 'connection-wizard-header', + templateUrl: './connection-wizard-header.component.html', + styleUrls:['./connection-wizard-header.component.less'] +}) + +export class ConnectionWizardHeaderComponent extends WizardHeaderBaseComponent{ + + constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService) { + super(); + } + + private _getReqOrCapName(isFromNode:boolean) { + const attributeReqOrCap:string = isFromNode ? 'requirement' : 'capability'; + if (this.connectWizardService.selectedMatch[attributeReqOrCap]) { + return this.connectWizardService.selectedMatch[attributeReqOrCap].getTitle(); + } else if (this.connectWizardService.selectedMatch.relationship) { + return this.connectWizardService.selectedMatch.relationship.relation[attributeReqOrCap]; + } + return ''; + } + + private getSelectedReqOrCapName = (isFromNode:boolean):string => { + if(!this.connectWizardService.selectedMatch){ + return ''; + } + return this._getReqOrCapName(this.connectWizardService.selectedMatch.isFromTo ? isFromNode : !isFromNode); + } +} + diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.module.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.module.ts new file mode 100644 index 0000000000..6b4b4128c1 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.module.ts @@ -0,0 +1,43 @@ +import {ToNodeStepComponent} from "./to-node-step/to-node-step.component"; +import {NgModule} from "@angular/core"; +import {FromNodeStepComponent} from "./from-node-step/from-node-step.component"; +import {PropertiesStepComponent} from "./properties-step/properties-step.component"; +import {ConnectionWizardService} from "./connection-wizard.service"; +import {SelectRequirementOrCapabilityModule} from "../../components/logic/select-requirement-or-capability/select-requirement-or-capability.module"; +import {PropertyTableModule} from "../../components/logic/properties-table/property-table.module"; +import {FormElementsModule} from "../../components/ui/form-components/form-elements.module"; +import {ConnectionWizardHeaderComponent} from "./connection-wizard-header/connection-wizard-header.component"; +import {ConnectionPropertiesViewComponent} from "./connection-properties-view/connection-properties-view.component"; +import {BrowserModule} from "@angular/platform-browser"; + +@NgModule({ + declarations: [ + FromNodeStepComponent, + ToNodeStepComponent, + PropertiesStepComponent, + ConnectionWizardHeaderComponent, + ConnectionPropertiesViewComponent + ], + imports: [ + FormElementsModule, + PropertyTableModule, + SelectRequirementOrCapabilityModule, + BrowserModule + ], + exports: [ + FromNodeStepComponent, + ToNodeStepComponent, + PropertiesStepComponent, + ConnectionWizardHeaderComponent, + ConnectionPropertiesViewComponent + ], + entryComponents: [FromNodeStepComponent, + ToNodeStepComponent, + PropertiesStepComponent, + ConnectionWizardHeaderComponent, + ConnectionPropertiesViewComponent + ], + providers: [ConnectionWizardService] +}) +export class ConnectionWizardModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.service.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.service.ts new file mode 100644 index 0000000000..a097fb04ea --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.service.ts @@ -0,0 +1,67 @@ +import {ConnectRelationModel} from "../../../models/graph/connectRelationModel"; +import {Injectable} from "@angular/core"; +import { Requirement, Capability} from "app/models"; +import {Dictionary} from "lodash"; +import {Match, Component, PropertyFEModel} from "app/models"; + +@Injectable() +export class ConnectionWizardService { + + connectRelationModel:ConnectRelationModel; + currentComponent:Component; + selectedMatch:Match; + changedCapabilityProperties:PropertyFEModel[]; + + constructor() { + this.changedCapabilityProperties = []; + } + + public setRelationMenuDirectiveObj = (connectRelationModel:ConnectRelationModel) => { + this.connectRelationModel = connectRelationModel; + // this.selectedCapability = rel + } + + + // getComponentInstanceIdOfSelectedCapability = (): string => { + // if(this.selectedMatch.capability){ + // if(this.selectedMatch.isFromTo) { + // return this.selectedMatch.toNode; + // } else { + // return this.selectedMatch.fromNode; + // } + // } + // return ''; + // + // } + + getOptionalRequirementsByInstanceUniqueId = (isFromTo: boolean, matchWith?:Capability): Dictionary<Requirement[]> => { + let requirements: Array<Requirement> = []; + _.forEach(this.connectRelationModel.possibleRelations, (match: Match) => { + if(!matchWith || match.capability.uniqueId == matchWith.uniqueId){ + if(match.isFromTo == isFromTo){ + requirements.push(match.requirement); + } + } + }); + requirements = _.uniqBy(requirements, (req:Requirement)=>{ + return req.ownerId + req.uniqueId + req.name; + }); + return _.groupBy(requirements, 'capability'); + } + + getOptionalCapabilitiesByInstanceUniqueId = (isFromTo: boolean, matchWith?:Requirement): Dictionary<Capability[]> => { + let capabilities: Array<Capability> = []; + _.forEach(this.connectRelationModel.possibleRelations, (match: Match) => { + if(!matchWith || match.requirement.uniqueId == matchWith.uniqueId){ + if(match.isFromTo == isFromTo){ + capabilities.push(match.capability); + } + } + }); + capabilities = _.uniqBy(capabilities, (cap:Capability)=>{ + return cap.ownerId + cap.uniqueId + cap.name; + }); + return _.groupBy(capabilities, 'type'); + } +} + diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.html new file mode 100644 index 0000000000..0c9d9e6e26 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.html @@ -0,0 +1,8 @@ +<select-requirement-or-capability [optionalRequirementsMap]="optionalRequirementsMap" + [optionalCapabilitiesMap]="optionalCapabilitiesMap" + [selectedReqOrCapModel]="connectWizardService.selectedMatch && (connectWizardService.selectedMatch.isFromTo ? connectWizardService.selectedMatch.requirement : connectWizardService.selectedMatch.capability)" + [currentComponent]="connectWizardService.currentComponent" + [componentInstanceId]="connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId" + (updateSelectedReqOrCap)="updateSelectedReqOrCap($event)" + (updateCapabilityProperties)="onCapabilityPropertiesUpdate($event)"> +</select-requirement-or-capability>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.ts new file mode 100644 index 0000000000..edbbf8a0a3 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.ts @@ -0,0 +1,49 @@ +import {Component, OnInit, Inject, forwardRef} from "@angular/core"; +import {IStepComponent} from "../../../../models/wizard-step"; +import {Dictionary} from "lodash"; +import { Match} from "app/models"; +import {ConnectionWizardService} from "../connection-wizard.service"; +import {Requirement} from "../../../../models/requirement"; +import {Capability} from "../../../../models/capability"; +import {PropertyModel} from "../../../../models/properties"; + +@Component({ + selector: 'from-node-step', + templateUrl: './from-node-step.component.html' +}) + +export class FromNodeStepComponent implements IStepComponent, OnInit{ + + constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService) {} + + optionalRequirementsMap: Dictionary<Requirement[]>; + optionalCapabilitiesMap: Dictionary<Capability[]>; + + ngOnInit(){ + this.optionalRequirementsMap = this.connectWizardService.getOptionalRequirementsByInstanceUniqueId(true); + this.optionalCapabilitiesMap = this.connectWizardService.getOptionalCapabilitiesByInstanceUniqueId(false); + } + + preventNext = ():boolean => { + return !this.connectWizardService.selectedMatch || (!this.connectWizardService.selectedMatch.capability && !this.connectWizardService.selectedMatch.requirement); + } + + preventBack = ():boolean => { + return true; + } + + onCapabilityPropertiesUpdate(capabilityProperties:Array<PropertyModel>) { + this.connectWizardService.selectedMatch.capabilityProperties = capabilityProperties; + } + + private updateSelectedReqOrCap = (selected:Requirement|Capability):void => { + if(!selected){ + this.connectWizardService.selectedMatch = null; + } else if(selected instanceof Requirement){ + this.connectWizardService.selectedMatch = new Match(<Requirement>selected, null, true, this.connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId, null); + } else{ + this.connectWizardService.selectedMatch = new Match(null,<Capability>selected , false, null, this.connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId); + } + } + +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.html new file mode 100644 index 0000000000..9e34893272 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.html @@ -0,0 +1,13 @@ +<div class="title"> + <span class="capability-name"> + {{(connectWizardService.selectedMatch.capability && connectWizardService.selectedMatch.capability.getTitle()) || connectWizardService.selectedMatch.relationship.relation.capability}} + </span> +</div> +<div class="properties-table-container"> + <properties-table class="properties-table" + (valueChanged)="propertyValueChanged($event)" + [fePropertiesMap]="capabilityPropertiesMap" + [selectedPropertyId]="''" + [hidePropertyType]="true"> + </properties-table> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.less b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.less new file mode 100644 index 0000000000..8e9e07c0d5 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.less @@ -0,0 +1,15 @@ +@import '../../../../../assets/styles/variables'; +.title{ + margin-bottom: 20px; + .capability-name-label{ + font-size: 13px; + } + .capability-name{ + font-family: @font-opensans-medium; + color: @main_color_a; + } +} +.properties-table-container{ + height: 362px; + overflow-y: auto; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.ts new file mode 100644 index 0000000000..3e48785a3c --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.ts @@ -0,0 +1,67 @@ +/** + * Created by ob0695 on 9/4/2017. + */ +/** + * Created by rc2122 on 9/4/2017. + */ +import {Component, Inject, forwardRef} from '@angular/core'; +import {IStepComponent} from "app/models" +import {ConnectionWizardService} from "../connection-wizard.service"; +import {PropertyFEModel} from "../../../../models/properties-inputs/property-fe-model"; +import {InstanceFePropertiesMap} from "../../../../models/properties-inputs/property-fe-map"; +import {PropertiesUtils} from "../../properties-assignment/services/properties.utils"; +import {ComponentInstanceServiceNg2} from "../../../services/component-instance-services/component-instance.service"; + +@Component({ + selector: 'properties-step', + templateUrl: './properties-step.component.html', + styleUrls: ['./properties-step.component.less'] +}) + +export class PropertiesStepComponent implements IStepComponent{ + + capabilityPropertiesMap: InstanceFePropertiesMap; + savingProperty:boolean = false; + + constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService, private componentInstanceServiceNg2:ComponentInstanceServiceNg2, private propertiesUtils:PropertiesUtils) { + + this.capabilityPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren({'capability' : connectWizardService.selectedMatch.capabilityProperties}, false); + } + + ngOnInit() { + this.connectWizardService.changedCapabilityProperties = []; + } + + onPropertySelectedUpdate = ($event) => { + console.log("==>" + 'PROPERTY VALUE SELECTED'); + // this.selectedFlatProperty = $event; + // let parentProperty:PropertyFEModel = this.propertiesService.getParentPropertyFEModelFromPath(this.instanceFePropertiesMap[this.selectedFlatProperty.instanceName], this.selectedFlatProperty.path); + // parentProperty.expandedChildPropertyId = this.selectedFlatProperty.path; + }; + + propertyValueChanged = (property: PropertyFEModel) => { + if (!property.isDeclared) { + const propChangedIdx = this.connectWizardService.changedCapabilityProperties.indexOf(property); + if (this.componentInstanceServiceNg2.hasPropertyChanged(property)) { + console.log("==>" + this.constructor.name + ": propertyValueChanged " + property); + if (propChangedIdx === -1) { + this.connectWizardService.changedCapabilityProperties.push(property); + } + } + else { + if (propChangedIdx !== -1) { + console.log("==>" + this.constructor.name + ": propertyValueChanged (reset to original) " + property); + this.connectWizardService.changedCapabilityProperties.splice(propChangedIdx, 1); + } + } + } + }; + + preventNext = ():boolean => { + return false; + } + + preventBack = ():boolean => { + return this.savingProperty; + } +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.html new file mode 100644 index 0000000000..67bb12e6fc --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.html @@ -0,0 +1,9 @@ +<select-requirement-or-capability [optionalRequirementsMap]="optionalRequirementsMap" + [optionalCapabilitiesMap]="optionalCapabilitiesMap" + [selectedReqOrCapModel]="connectWizardService.selectedMatch.isFromTo ? connectWizardService.selectedMatch.capability : connectWizardService.selectedMatch.requirement" + [selectedReqOrCapOption]="displayRequirementsOrCapabilities" + [currentComponent]="connectWizardService.currentComponent" + [componentInstanceId]="connectWizardService.connectRelationModel.toNode.componentInstance.uniqueId" + (updateSelectedReqOrCap)="updateSelectedReqOrCap($event)" + (updateCapabilityProperties)="onCapabilityPropertiesUpdate($event)"> +</select-requirement-or-capability>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.ts new file mode 100644 index 0000000000..9c7bf4dfe6 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.ts @@ -0,0 +1,69 @@ +import {Component, forwardRef, Inject} from '@angular/core'; +import {IStepComponent} from "app/models" +import {Dictionary} from "lodash"; +import {ConnectionWizardService} from "../connection-wizard.service"; +import {Match} from "../../../../models/graph/match-relation"; +import {Requirement} from "../../../../models/requirement"; +import {Capability} from "../../../../models/capability"; +import {PropertyModel} from "../../../../models/properties"; + +@Component({ + selector: 'to-node-step', + templateUrl: './to-node-step.component.html' +}) + +export class ToNodeStepComponent implements IStepComponent{ + + displayRequirementsOrCapabilities:string; //get 'Requirement' or 'Capability' + optionalRequirementsMap: Dictionary<Requirement[]> = {}; + optionalCapabilitiesMap: Dictionary<Capability[]> ={}; + + constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService) { + } + + ngOnInit(){ + if(this.connectWizardService.selectedMatch.isFromTo){ + this.displayRequirementsOrCapabilities = 'Capability'; + this.optionalRequirementsMap = {}; + this.optionalCapabilitiesMap = this.connectWizardService.getOptionalCapabilitiesByInstanceUniqueId(true, this.connectWizardService.selectedMatch.requirement); + }else{ + this.displayRequirementsOrCapabilities = 'Requirement'; + this.optionalRequirementsMap = this.connectWizardService.getOptionalRequirementsByInstanceUniqueId(false, this.connectWizardService.selectedMatch.capability); + this.optionalCapabilitiesMap = {} + } + + + } + + preventNext = ():boolean => { + return !this.connectWizardService.selectedMatch.capability || !this.connectWizardService.selectedMatch.requirement; + } + + preventBack = ():boolean => { + return false; + } + + onCapabilityPropertiesUpdate(capabilityProperties:Array<PropertyModel>) { + this.connectWizardService.selectedMatch.capabilityProperties = capabilityProperties; + } + + private updateSelectedReqOrCap = (selected:Requirement|Capability):void => { + if (!selected) { + if (this.connectWizardService.selectedMatch.isFromTo) { + this.connectWizardService.selectedMatch.capability = undefined; + this.connectWizardService.selectedMatch.toNode = undefined; + } else { + this.connectWizardService.selectedMatch.requirement = undefined; + this.connectWizardService.selectedMatch.fromNode = undefined; + } + } else if (selected instanceof Requirement) { + this.connectWizardService.selectedMatch.requirement = <Requirement>selected; + this.connectWizardService.selectedMatch.fromNode = this.connectWizardService.connectRelationModel.toNode.componentInstance.uniqueId; + } else { + this.connectWizardService.selectedMatch.capability = <Capability>selected; + this.connectWizardService.selectedMatch.toNode = this.connectWizardService.connectRelationModel.toNode.componentInstance.uniqueId; + } + this.connectWizardService.selectedMatch.relationship = undefined; + } + +} diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts index 1c6f51314d..203c75dd11 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts @@ -17,70 +17,43 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - import { NgModule } from "@angular/core"; -import { PropertiesAssignmentComponent } from "./properties-assignment.page.component"; -import { HierarchyNavigationComponent } from "./../../components/hierarchy-navigtion/hierarchy-navigation.component"; -import { BrowserModule } from "@angular/platform-browser"; -import { FormsModule } from "@angular/forms"; -import { HttpModule } from "@angular/http"; -import { TabModule } from '../../shared/tabs/tabs.module'; -import { CheckboxModule} from '../../shared/checkbox/checkbox.module'; -import { PropertiesTableComponent } from '../../components/properties-table/properties-table.component'; -import { InputsTableComponent } from '../../components/inputs-table/inputs-table.component'; -import { ContentAfterLastDotPipe } from "../../pipes/contentAfterLastDot.pipe"; -import { SearchFilterPipe } from "../../pipes/searchFilter.pipe"; -import { FilterChildPropertiesPipe } from "../../pipes/filterChildProperties.pipe"; -import { DataTypeService } from './../../services/data-type.service'; -import { PropertiesService } from './../../services/properties.service'; -import { HierarchyNavService } from './../../services/hierarchy-nav.service'; -import { PropertiesUtils } from './properties.utils'; -import { DynamicElementModule } from 'app/ng2/components/dynamic-element/dynamic-element.module'; -import { DynamicPropertyComponent } from './../../components/properties-table/dynamic-property/dynamic-property.component'; -import { PopoverModule } from "../../components/popover/popover.module"; -import { ModalModule } from "../../components/modal/modal.module"; -import { FilterPropertiesAssignmentComponent } from "./../../components/filter-properties-assignment/filter-properties-assignment.component"; -import { GroupByPipe } from 'app/ng2/pipes/groupBy.pipe'; -import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; -import {TooltipModule} from "../../components/tooltip/tooltip.module"; -import { ComponentModeService } from "app/ng2/services/component-mode.service" -import {LoaderComponent} from "app/ng2/components/loader/loader.component" +import {HierarchyNavigationComponent} from "../../components/logic/hierarchy-navigtion/hierarchy-navigation.component"; +import {HttpModule} from "@angular/http"; +import {FormsModule} from "@angular/forms"; +import {PropertyTableModule} from "../../components/logic/properties-table/property-table.module"; +import {UiElementsModule} from "../../components/ui/ui-elements.module"; +import {GlobalPipesModule} from "../../pipes/global-pipes.module"; +import {BrowserModule} from "@angular/platform-browser"; +import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component"; +import {InputsTableComponent} from "../../components/logic/inputs-table/inputs-table.component"; +import {PropertiesService} from "../../services/properties.service"; +import {DataTypeService} from "../../services/data-type.service"; +import {PropertiesAssignmentComponent} from "./properties-assignment.page.component"; +import {HierarchyNavService} from "./services/hierarchy-nav.service"; +import {PropertiesUtils} from "./services/properties.utils"; +import {ComponentModeService} from "../../services/component-services/component-mode.service"; @NgModule({ declarations: [ PropertiesAssignmentComponent, - PropertiesTableComponent, InputsTableComponent, - ContentAfterLastDotPipe, - GroupByPipe, - KeysPipe, - SearchFilterPipe, - FilterChildPropertiesPipe, HierarchyNavigationComponent, - DynamicPropertyComponent, - // PopoverContentComponent, - // PopoverComponent, - FilterPropertiesAssignmentComponent, - LoaderComponent + FilterPropertiesAssignmentComponent ], imports: [ BrowserModule, FormsModule, HttpModule, - TabModule, - CheckboxModule, - DynamicElementModule, - PopoverModule, - TooltipModule, - ModalModule - ], + GlobalPipesModule, + PropertyTableModule, + UiElementsModule], + entryComponents: [PropertiesAssignmentComponent], exports: [ PropertiesAssignmentComponent - // PopoverContentComponent, - // PopoverComponent ], - providers: [PropertiesService, HierarchyNavService, PropertiesUtils, DataTypeService, ContentAfterLastDotPipe, GroupByPipe, KeysPipe, ComponentModeService] + providers: [PropertiesService, HierarchyNavService, PropertiesUtils, DataTypeService, ComponentModeService] }) export class PropertiesAssignmentModule { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html index be7e03dccd..beea3fe73f 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html @@ -11,6 +11,7 @@ [propertyNameSearchText]="searchPropertyName" [readonly]="isReadonly" [isLoading]="loadingProperties" + [hasDeclareOption]="true" (valueChanged)="propertyValueChanged($event)" (propertySelected)="propertySelected($event)" (selectPropertyRow)="selectPropertyRow($event)" @@ -31,12 +32,12 @@ </tabs> <div class="header"> <div class="search-filter-container" [class.without-filter]="isInpusTabSelected"> - <span *ngIf="displayClearSearch && !isInpusTabSelected" (click)="clickOnClearSearch()" class="clear-filter">Clear All</span> - <input type="text" class="search-box" placeholder="Search" [(ngModel)]="searchQuery" /> - <span class="sprite search-icon"></span> + <span *ngIf="displayClearSearch && !isInpusTabSelected" (click)="clickOnClearSearch()" class="clear-filter" data-tests-id="clear-filter-button">Clear All</span> + <input type="text" class="search-box" placeholder="Search" [(ngModel)]="searchQuery" data-tests-id="search-box"/> + <span class="sprite search-icon" data-tests-id="search-button"></span> <filter-properties-assignment *ngIf="!isInpusTabSelected" #advanceSearch class="advance-search" [componentType]="component.componentType" (searchProperties)="searchPropertiesInstances($event)"></filter-properties-assignment> </div> - <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly" (click)="declareProperties()">Declare</button> + <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly" (click)="declareProperties()" data-tests-id="declare-button">Declare</button> </div> </div> <div class="right-column gray-border"> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index 82754f13f0..9603648bd8 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -20,21 +20,22 @@ import {Component, ViewChild, ElementRef, Renderer, Inject} from "@angular/core"; import { PropertiesService } from "../../services/properties.service"; -import { HierarchyNavService } from "../../services/hierarchy-nav.service"; -import { PropertiesUtils } from './properties.utils'; import { PropertyFEModel, InstanceFePropertiesMap, InstanceBePropertiesMap, InstancePropertiesAPIMap, Component as ComponentData, FilterPropertiesAssignmentData } from "app/models"; -import { PROPERTY_TYPES, ResourceType } from "app/utils"; +import { ResourceType } from "app/utils"; import property = require("lodash/property"); import {ComponentServiceNg2} from "../../services/component-services/component.service"; import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service" -import { InputBEModel, InputFEModel, ComponentInstance, PropertyBEModel, DerivedPropertyType, DerivedFEProperty, ResourceInstance, SimpleFlatProperty } from "app/models"; -import {HierarchyDisplayOptions} from "../../components/hierarchy-navigtion/hierarchy-display-options" -import {PropertyRowSelectedEvent} from "./../../components/properties-table/properties-table.component"; +import { InputBEModel, InputFEModel, ComponentInstance, PropertyBEModel, DerivedFEProperty, ResourceInstance, SimpleFlatProperty } from "app/models"; import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; -import {FilterPropertiesAssignmentComponent} from "../../components/filter-properties-assignment/filter-properties-assignment.component"; -import { ComponentModeService } from "app/ng2/services/component-mode.service" import {WorkspaceMode, EVENTS} from "../../../utils/constants"; import {EventListenerService} from "app/services/event-listener-service" +import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options"; +import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component"; +import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component"; +import {HierarchyNavService} from "./services/hierarchy-nav.service"; +import {PropertiesUtils} from "./services/properties.utils"; +import {ComponentModeService} from "../../services/component-services/component-mode.service"; + @Component({ templateUrl: './properties-assignment.page.component.html', styleUrls: ['./properties-assignment.page.component.less'] diff --git a/catalog-ui/src/app/ng2/services/hierarchy-nav.service.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/hierarchy-nav.service.ts index 016b04788e..016b04788e 100644 --- a/catalog-ui/src/app/ng2/services/hierarchy-nav.service.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/hierarchy-nav.service.ts diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts index d8d991d218..8f46c6f603 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts @@ -19,11 +19,10 @@ */ import { Injectable } from '@angular/core'; -import { DataTypeModel, PropertyFEModel, PropertyBEModel, InstanceBePropertiesMap, InstanceFePropertiesMap, SchemaProperty, DerivedFEProperty, DerivedFEPropertyMap, DerivedPropertyType, InputFEModel} from "app/models"; +import { DataTypeModel, PropertyFEModel, PropertyBEModel, InstanceBePropertiesMap, InstanceFePropertiesMap, DerivedFEProperty, DerivedPropertyType, InputFEModel} from "app/models"; import { DataTypeService } from "app/ng2/services/data-type.service"; import { PropertiesService } from "app/ng2/services/properties.service"; -import { PROPERTY_TYPES } from "app/utils"; -import { UUID } from "angular2-uuid"; +import { PROPERTY_TYPES, PROPERTY_DATA } from "app/utils"; @Injectable() export class PropertiesUtils { @@ -106,8 +105,16 @@ export class PropertiesUtils { public initValueObjectRef = (property: PropertyFEModel): void => { if (property.derivedDataType == DerivedPropertyType.SIMPLE || property.isDeclared) { //if property is declared, it gets a simple input instead. List and map values and pseudo-children will be handled in property component property.valueObj = property.value || property.defaultValue; - - if (property.isDeclared && typeof property.valueObj == 'object') property.valueObj = JSON.stringify(property.valueObj); + if (property.isDeclared) { + if(typeof property.valueObj == 'object'){ + property.valueObj = JSON.stringify(property.valueObj); + } + }else if(property.valueObj && + property.type !== PROPERTY_TYPES.STRING && + property.type !== PROPERTY_TYPES.JSON && + PROPERTY_DATA.SCALAR_TYPES.indexOf(property.type) == -1){ + property.valueObj = JSON.parse(property.valueObj);//The valueObj contains the real value ans not the value as string + } } else { if (property.derivedDataType == DerivedPropertyType.LIST) { property.valueObj = _.merge([], JSON.parse(property.defaultValue || '[]'), JSON.parse(property.value || '[]')); //value object should be merged value and default value. Value takes higher precendence. Set valueObj to empty obj if undefined. diff --git a/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts b/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts new file mode 100644 index 0000000000..1d81a1a4bf --- /dev/null +++ b/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts @@ -0,0 +1,24 @@ +import {ContentAfterLastDotPipe} from "./contentAfterLastDot.pipe"; +import {SearchFilterPipe} from "./searchFilter.pipe"; +import {KeysPipe} from "./keys.pipe"; +import {GroupByPipe} from "./groupBy.pipe"; +import {NgModule} from "@angular/core"; + +@NgModule({ + declarations: [ + ContentAfterLastDotPipe, + GroupByPipe, + KeysPipe, + SearchFilterPipe + + ], + + exports: [ + ContentAfterLastDotPipe, + GroupByPipe, + KeysPipe, + SearchFilterPipe + ] +}) + +export class GlobalPipesModule {} diff --git a/catalog-ui/src/app/ng2/services/authentication.service.ts b/catalog-ui/src/app/ng2/services/authentication.service.ts index 876385c832..1c6502dd0d 100644 --- a/catalog-ui/src/app/ng2/services/authentication.service.ts +++ b/catalog-ui/src/app/ng2/services/authentication.service.ts @@ -18,26 +18,23 @@ * ============LICENSE_END========================================================= */ -import { Injectable } from '@angular/core'; -import { sdc2Config } from './../../../main'; +import {Injectable, Inject} from '@angular/core'; import {IAppConfigurtaion, ICookie} from "../../models/app-config"; import {Response, Headers, RequestOptions, Http} from '@angular/http'; import {Cookie2Service} from "./cookie.service"; import { Observable } from 'rxjs/Observable'; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; @Injectable() export class AuthenticationService { - private cookieService:Cookie2Service; - private http:Http; - - constructor(cookieService:Cookie2Service, http: Http) { + constructor(private cookieService:Cookie2Service, private http: Http, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { this.cookieService = cookieService; this.http = http; } private getAuthHeaders():any { - let cookie:ICookie = sdc2Config.cookie; + let cookie:ICookie = this.sdcConfig.cookie; let authHeaders:any = {}; authHeaders[cookie.userFirstName] = this.cookieService.getFirstName(); authHeaders[cookie.userLastName] = this.cookieService.getLastName(); @@ -51,7 +48,7 @@ export class AuthenticationService { headers: new Headers(this.getAuthHeaders()) }); - let authUrl = sdc2Config.api.root + sdc2Config.api.GET_user_authorize; + let authUrl = this.sdcConfig.api.root + this.sdcConfig.api.GET_user_authorize; return this.http .get(authUrl, options) .map((res: Response) => res.json()); diff --git a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts index 27de59de82..b852539edd 100644 --- a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts +++ b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts @@ -18,22 +18,23 @@ * ============LICENSE_END========================================================= */ -import {Injectable} from '@angular/core'; +import {Injectable, Inject} from '@angular/core'; import {Response, RequestOptions, Headers} from '@angular/http'; import { Observable } from 'rxjs/Observable'; -import {sdc2Config} from "../../../../main"; -import {PropertyBEModel} from "app/models"; +import {PropertyFEModel, PropertyBEModel} from "app/models"; import {CommonUtils} from "app/utils"; import {Component, ComponentInstance, InputModel} from "app/models"; import { HttpService } from '../http.service'; +import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config"; +import {isEqual} from "lodash"; @Injectable() export class ComponentInstanceServiceNg2 { protected baseUrl; - constructor(private http: HttpService) { - this.baseUrl = sdc2Config.api.root + sdc2Config.api.component_api_root; + constructor(private http: HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) { + this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root; } getComponentInstanceProperties(component: Component, componentInstanceId: string): Observable<Array<PropertyBEModel>> { @@ -59,6 +60,24 @@ export class ComponentInstanceServiceNg2 { }) } + getInstanceCapabilityProperties(component: Component, componentInstanceId: string, capabilityType: string, capabilityName: string): Observable<Array<PropertyBEModel>> { + + return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstanceId + '/capability/' + capabilityType + + '/capabilityName/' + capabilityName + '/properties') + .map((res: Response) => { + return CommonUtils.initBeProperties(res.json()); + }) + } + + updateInstanceCapabilityProperties(component: Component, componentInstanceId: string, capabilityType: string, capabilityName: string, properties: PropertyBEModel[]): Observable<PropertyBEModel[]> { + + return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstanceId + '/capability/' + capabilityType + + '/capabilityName/' + capabilityName +'/properties', properties) + .map((res: Response) => { + return res.json().map((resProperty) => new PropertyBEModel(resProperty)); + }) + } + updateInstanceInput(component: Component, componentInstanceId: string, input: PropertyBEModel): Observable<PropertyBEModel> { return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstance/' + componentInstanceId + '/input', input) @@ -67,5 +86,9 @@ export class ComponentInstanceServiceNg2 { }) } - + hasPropertyChanged(property: PropertyFEModel) { + let oldValue: any = property.value; + const newValue = property.getJSONValue(); + return ((oldValue || newValue) && !isEqual(oldValue, newValue)); + } } diff --git a/catalog-ui/src/app/ng2/services/component-mode.service.ts b/catalog-ui/src/app/ng2/services/component-services/component-mode.service.ts index 2e60f6ac57..b0cc1b8f1a 100644 --- a/catalog-ui/src/app/ng2/services/component-mode.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/component-mode.service.ts @@ -22,7 +22,7 @@ * Created by rc2122 on 5/23/2017. */ import { Injectable } from '@angular/core'; -import {WorkspaceMode, ComponentState, Role} from "../../utils/constants"; +import {WorkspaceMode, ComponentState, Role} from "../../../utils/constants"; import { Component as ComponentData } from "app/models"; import { CacheService } from "app/services/cache-service" diff --git a/catalog-ui/src/app/ng2/services/component-services/component.service.ts b/catalog-ui/src/app/ng2/services/component-services/component.service.ts index c648711d5d..ba1cb15561 100644 --- a/catalog-ui/src/app/ng2/services/component-services/component.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/component.service.ts @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import {Injectable} from '@angular/core'; +import {Injectable, Inject} from '@angular/core'; import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise'; @@ -27,11 +27,11 @@ import { Component, PropertyBEModel, InstancePropertiesAPIMap, FilterPropertiesA import {downgradeInjectable} from '@angular/upgrade/static'; import {COMPONENT_FIELDS} from "app/utils"; import {ComponentGenericResponse} from "../responses/component-generic-response"; -import {sdc2Config} from "../../../../main"; import {InstanceBePropertiesMap} from "../../../models/properties-inputs/property-fe-map"; import {API_QUERY_PARAMS} from "app/utils"; import { ComponentType, ServerTypeUrl } from "../../../utils/constants"; import { HttpService } from '../http.service'; +import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config"; declare var angular:angular.IAngularStatic; @@ -40,8 +40,8 @@ export class ComponentServiceNg2 { protected baseUrl; - constructor(private http:HttpService) { - this.baseUrl = sdc2Config.api.root + sdc2Config.api.component_api_root; + constructor(private http:HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) { + this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root; } private getComponentDataByFieldsName(componentType:string, componentId: string, fields:Array<string>):Observable<ComponentGenericResponse> { @@ -151,17 +151,6 @@ export class ComponentServiceNg2 { .map((res: Response) => { return res.json(); }); - - // return {'ExtVL 0':[{definition: false,name:"network_assignments",password:false,required:true,type:"org.openecomp.datatypes.network.NetworkAssignments",uniqueId:"623cca1c-d605-4c9c-9f2b-935ec85ebcf8.network_assignments"}, - // {definition: false,name: "exVL_naming",password: false,required: true,type: "org.openecomp.datatypes.Naming",uniqueId: "623cca1c-d605-4c9c-9f2b-935ec85ebcf8.exVL_naming"}, - // {definition: false,name: "network_flows",password: false,required: false,type: "org.openecomp.datatypes.network.NetworkFlows",uniqueId: "623cca1c-d605-4c9c-9f2b-935ec85ebcf8.network_flows"}, - // {definition: false,name: "provider_network",password: false,required: true,type: "org.openecomp.datatypes.network.ProviderNetwork",uniqueId: "623cca1c-d605-4c9c-9f2b-935ec85ebcf8.provider_network"}, - // {definition: false,name: "network_homing",password: false,required: true,type: "org.openecomp.datatypes.EcompHoming",uniqueId: "623cca1c-d605-4c9c-9f2b-935ec85ebcf8.network_homing"}], - // 'NetworkCP 0':[{definition: false,description: "identifies MAC address assignments to the CP",name: "mac_requirements",password: false,required: false,type: "org.openecomp.datatypes.network.MacRequirements",uniqueId: "26ec2bfd-b904-46c7-87ed-b32775120f2c.mac_requirements"}], - // 'NetworkCP 1':[{definition: false,description: "identifies MAC address assignments to the CP",name: "mac_requirements",password: false,required: false,type: "org.openecomp.datatypes.network.MacRequirements",uniqueId: "26ec2bfd-b904-46c7-87ed-b32775120f2c.mac_requirements"}]}; - - } } -angular.module('Sdc.Services').factory('ComponentServiceNg2', downgradeInjectable(ComponentServiceNg2)); // This is in order to use the service in angular1 till we finish remove all angular1 code diff --git a/catalog-ui/src/app/ng2/services/component-services/service.service.ts b/catalog-ui/src/app/ng2/services/component-services/service.service.ts index ec912bbcf5..f38dbef595 100644 --- a/catalog-ui/src/app/ng2/services/component-services/service.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/service.service.ts @@ -18,15 +18,15 @@ * ============LICENSE_END========================================================= */ -import { Injectable } from '@angular/core'; +import { Injectable, Inject } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise'; import { Response } from '@angular/http'; import {Service} from "app/models"; import { downgradeInjectable } from '@angular/upgrade/static'; -import {sdc2Config} from "../../../../main"; import { HttpService } from '../http.service'; +import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config"; @Injectable() @@ -34,8 +34,8 @@ export class ServiceServiceNg2 { protected baseUrl = ""; - constructor(private http: HttpService) { - this.baseUrl = sdc2Config.api.root + sdc2Config.api.component_api_root; + constructor(private http: HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) { + this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root; } validateConformanceLevel(service: Service): Observable<boolean> { @@ -47,5 +47,3 @@ export class ServiceServiceNg2 { } } - -angular.module('Sdc.Services').factory('ServiceServiceNg2', downgradeInjectable(ServiceServiceNg2)); // This is in order to use the service in angular1 till we finish remove all angular1 code diff --git a/catalog-ui/src/app/ng2/services/config.service.ts b/catalog-ui/src/app/ng2/services/config.service.ts index cac850e91c..9bb7b7a075 100644 --- a/catalog-ui/src/app/ng2/services/config.service.ts +++ b/catalog-ui/src/app/ng2/services/config.service.ts @@ -22,13 +22,11 @@ * Created by ob0695 on 4/9/2017. */ -import { Injectable } from '@angular/core'; +import { Injectable, Inject } from '@angular/core'; import { Http, Response } from '@angular/http'; import 'rxjs/add/operator/toPromise'; import {IAppConfigurtaion, ValidationConfiguration, Validations} from "app/models"; -import {sdc2Config} from './../../../main'; - -declare var __ENV__: string; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; @Injectable() export class ConfigService { @@ -36,12 +34,12 @@ export class ConfigService { private baseUrl; public configuration: IAppConfigurtaion; - constructor(private http: Http) { - this.baseUrl = sdc2Config.api.root + sdc2Config.api.component_api_root; + constructor(private http: Http, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { + this.baseUrl = this.sdcConfig.api.root + this.sdcConfig.api.component_api_root; } loadValidationConfiguration(): Promise<ValidationConfiguration> { - let url: string = sdc2Config.validationConfigPath; + let url: string = this.sdcConfig.validationConfigPath; let promise: Promise<ValidationConfiguration> = this.http.get(url).map((res: Response) => res.json()).toPromise(); promise.then((validationData: Validations) => { ValidationConfiguration.validation = validationData; diff --git a/catalog-ui/src/app/ng2/services/cookie.service.ts b/catalog-ui/src/app/ng2/services/cookie.service.ts index e5f04f7afd..2a783fdd48 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 } from '@angular/core'; +import {Injectable, Inject} from '@angular/core'; import {IAppConfigurtaion, ICookie} from "../../models/app-config"; -import {sdc2Config} from './../../../main'; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; @Injectable() export class Cookie2Service { @@ -28,8 +28,8 @@ export class Cookie2Service { private cookie:ICookie; private cookiePrefix:string; - constructor() { - this.cookie = sdc2Config.cookie; + constructor(@Inject(SdcConfigToken) sdcConfig:ISdcConfig) { + this.cookie = sdcConfig.cookie; this.cookiePrefix = ''; let junctionName:string = this.getCookieByName(this.cookie.junctionName); diff --git a/catalog-ui/src/app/ng2/services/http.service.ts b/catalog-ui/src/app/ng2/services/http.service.ts index 21fe09023a..2785688ace 100644 --- a/catalog-ui/src/app/ng2/services/http.service.ts +++ b/catalog-ui/src/app/ng2/services/http.service.ts @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import {Injectable} from '@angular/core'; +import {Injectable, Inject} from '@angular/core'; import {Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers} from '@angular/http'; import {Observable} from 'rxjs/Observable'; import {UUID} from 'angular2-uuid'; @@ -27,15 +27,15 @@ import 'rxjs/add/operator/catch'; import 'rxjs/add/observable/throw'; import {Dictionary} from "../../utils/dictionary/dictionary"; import {SharingService, CookieService} from "app/services"; -import {sdc2Config} from './../../../main'; import { ModalService } from "app/ng2/services/modal.service"; import { ServerErrorResponse } from "app/models"; -import { ErrorMessageComponent } from 'app/ng2/components/modal/error-message/error-message.component'; +import {ErrorMessageComponent} from "../components/ui/modal/error-message/error-message.component"; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; @Injectable() export class HttpService extends Http { - constructor(backend: XHRBackend, options: RequestOptions, private sharingService: SharingService, private cookieService: CookieService, private modalService: ModalService) { + constructor(backend: XHRBackend, options: RequestOptions, private sharingService: SharingService, private cookieService: CookieService, private modalService: ModalService, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { super(backend, options); this._defaultOptions.withCredentials = true; this._defaultOptions.headers.append(cookieService.getUserIdSuffix(), cookieService.getUserId()); @@ -73,7 +73,7 @@ export class HttpService extends Http { private getUuidValue = (url: string) :string => { let map:Dictionary<string, string> = this.sharingService.getUuidMap(); - if (map && url.indexOf(sdc2Config.api.root) > 0) { + if (map && url.indexOf(this.sdcConfig.api.root) > 0) { map.forEach((key:string) => { if (url.indexOf(key) !== -1) { return this.sharingService.getUuidValue(key); @@ -93,4 +93,8 @@ export class HttpService extends Http { return Observable.throw(response); }; + public static replaceUrlParams(url:string, urlParams:{[index:string]:any}):string { + return url.replace(/:(\w+)/g, (m, p1):string => urlParams[p1] || ''); + } + } diff --git a/catalog-ui/src/app/ng2/services/modal.service.ts b/catalog-ui/src/app/ng2/services/modal.service.ts index 65ff870769..22b56c7004 100644 --- a/catalog-ui/src/app/ng2/services/modal.service.ts +++ b/catalog-ui/src/app/ng2/services/modal.service.ts @@ -1,6 +1,11 @@ -import { Injectable, Type, ViewContainerRef, ApplicationRef, ComponentFactory, ComponentFactoryResolver, ComponentRef } from '@angular/core'; -import { ModalModel, ButtonModel } from 'app/models'; -import { ModalComponent } from 'app/ng2/components/modal/modal.component'; +import { + Injectable, Type, ViewContainerRef, ApplicationRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, + +} from '@angular/core'; +import { ModalModel, ButtonModel, StepModel } from 'app/models'; +import {MultiStepsWizardComponent} from "../components/ui/multi-steps-wizard/multi-steps-wizard.component"; +import {ModalComponent} from "../components/ui/modal/modal.component"; +import {WizardHeaderBaseComponent} from "app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component"; @Injectable() @@ -54,6 +59,23 @@ export class ModalService { return customModal; } + public createMultiStepsWizard = (title: string, steps:Array<StepModel>, callback: Function, dynamicHeaderType?: Type<WizardHeaderBaseComponent>): ComponentRef<MultiStepsWizardComponent> => { + let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline blue', this.closeCurrentModal); + let modalModel: ModalModel = new ModalModel('xl', title, '', [cancelButton]); + let wizardInstance: ComponentRef<MultiStepsWizardComponent> = this.createDynamicComponent(MultiStepsWizardComponent); + wizardInstance.instance.input = modalModel; + wizardInstance.instance.steps = steps; + wizardInstance.instance.callback = callback; + if(dynamicHeaderType){ + let dynamicHeader = this.createDynamicComponent(dynamicHeaderType, wizardInstance.instance.dynamicHeaderContainer); + wizardInstance.instance.dynamicHeader = dynamicHeader; + wizardInstance.instance.dynamicHeader.instance.currentStepIndex = 0; + } + this.addDynamicContentToModal(wizardInstance, steps[0].component); + this.currentModal = wizardInstance; + return wizardInstance; + } + public closeCurrentModal = () => { if (!this.currentModal) return; @@ -62,7 +84,7 @@ export class ModalService { } - public addDynamicContentToModal = (modalInstance: ComponentRef<ModalComponent>, dynamicComponentType: Type<any>, dynamicComponentInput: any) => { + public addDynamicContentToModal = (modalInstance: ComponentRef<ModalComponent>, dynamicComponentType: Type<any>, dynamicComponentInput?: any) => { let dynamicContent = this.createDynamicComponent(dynamicComponentType, modalInstance.instance.dynamicContentContainer); dynamicContent.instance.input = dynamicComponentInput; @@ -72,14 +94,13 @@ export class ModalService { //Creates a component dynamically (aka during runtime). If a view container is not specified, it will append the new component to the app root. //To subscribe to an event from invoking component: componentRef.instance.clicked.subscribe((m) => console.log(m.name)); - private createDynamicComponent<T>(componentType: Type<T>, viewContainerRef?:ViewContainerRef): ComponentRef<any> { + private createDynamicComponent<T>(componentType: Type<T>, viewContainerRef?:ViewContainerRef): ComponentRef<T> { viewContainerRef = viewContainerRef || this.getRootViewContainerRef(); viewContainerRef.clear(); - let factory: ComponentFactory<any> = this.componentFactoryResolver.resolveComponentFactory(componentType); //Ref: https://angular.io/guide/dynamic-component-loader - let componentRef = viewContainerRef.createComponent(factory); - + let factory: ComponentFactory<T> = this.componentFactoryResolver.resolveComponentFactory(componentType); //Ref: https://angular.io/guide/dynamic-component-loader + let componentRef: ComponentRef<T> = viewContainerRef.createComponent(factory); return componentRef; } @@ -87,4 +108,6 @@ export class ModalService { private getRootViewContainerRef(): ViewContainerRef { return this.applicationRef.components[0].instance.viewContainerRef; } -}
\ No newline at end of file +} + + diff --git a/catalog-ui/src/app/ng2/services/properties.service.ts b/catalog-ui/src/app/ng2/services/properties.service.ts index 6f15de858a..86cd2f5c72 100644 --- a/catalog-ui/src/app/ng2/services/properties.service.ts +++ b/catalog-ui/src/app/ng2/services/properties.service.ts @@ -19,16 +19,12 @@ */ import { Injectable } from '@angular/core'; -import { DataTypeModel, PropertyFEModel, PropertyBEModel, SchemaProperty, PropertyDeclareAPIModel, DerivedFEProperty, DerivedFEPropertyMap, DerivedPropertyType, InputFEModel} from "app/models"; -import { DataTypeService } from "./data-type.service"; -import { PROPERTY_TYPES } from "app/utils"; -import { ContentAfterLastDotPipe } from "../pipes/contentAfterLastDot.pipe"; -import { UUID } from "angular2-uuid"; +import { PropertyFEModel, PropertyBEModel, PropertyDeclareAPIModel, DerivedFEProperty} from "app/models"; @Injectable() export class PropertiesService { - constructor(private dataTypeService: DataTypeService, private contentAfterLastDotPipe: ContentAfterLastDotPipe) { + constructor() { } public getParentPropertyFEModelFromPath = (properties: Array<PropertyFEModel>, path: string) => { diff --git a/catalog-ui/src/app/ng2/services/user.service.ts b/catalog-ui/src/app/ng2/services/user.service.ts new file mode 100644 index 0000000000..87e90432dc --- /dev/null +++ b/catalog-ui/src/app/ng2/services/user.service.ts @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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 { Injectable, Inject } from "@angular/core"; +import { Headers } from "@angular/http"; +import { Observable } from "rxjs/Observable"; +import { HttpService } from "./http.service"; +import { Cookie2Service } from "./cookie.service"; +import { IUserProperties } from "../../models/user"; + +import {ICookie} from "../../models/app-config"; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; + +@Injectable() +export class UserService { + private url:string; + private authorizeUrl:string; + + private _loggedinUser:IUserProperties; + + constructor(private httpService:HttpService, + private cookieService:Cookie2Service, + @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { + this.url = this.sdcConfig.api.root + this.sdcConfig.api.GET_user; + this.authorizeUrl = this.sdcConfig.api.root + this.sdcConfig.api.GET_user_authorize; + } + + public authorize() :Observable<IUserProperties> { + let cookie:ICookie = this.sdcConfig.cookie; + let authorizeHeaders:Headers = new Headers(); + authorizeHeaders.set(cookie.userFirstName, this.cookieService.getFirstName()); + authorizeHeaders.set(cookie.userLastName, this.cookieService.getLastName()); + authorizeHeaders.set(cookie.userEmail, this.cookieService.getEmail()); + authorizeHeaders.set(cookie.userIdSuffix, this.cookieService.getUserId()); + + return this.httpService.get( + this.authorizeUrl, + { headers: authorizeHeaders } + ).map(resp => resp.json()); + } + + public getAllUsers() :Observable<IUserProperties[]> { + return this.httpService.get( + this.sdcConfig.api.root + this.sdcConfig.api.GET_all_users + ).map(resp => resp.json()); + } + + public getUser(userId:string) :Observable<IUserProperties> { + return this.httpService.get( + HttpService.replaceUrlParams(this.url, { id: userId }) + ).map(resp => resp.json()); + } + + public createUser(userData:{[index:string]: any}) :Observable<IUserProperties> { + return this.httpService.post( + this.sdcConfig.api.root + this.sdcConfig.api.POST_create_user, + userData + ).map(resp => resp.json()); + } + + public deleteUser(userId:string) :Observable<IUserProperties> { + return this.httpService.delete( + HttpService.replaceUrlParams(this.sdcConfig.api.root + this.sdcConfig.api.DELETE_delete_user, { id: userId }) + ).map(resp => resp.json()); + } + + public editUserRole(userId:string, role:string) :Observable<IUserProperties> { + return this.httpService.post( + HttpService.replaceUrlParams(this.sdcConfig.api.root + this.sdcConfig.api.POST_edit_user_role, { id: userId }), + { role: role } + ).map(resp => resp.json()); + } + + public getLoggedinUser():IUserProperties { + return this._loggedinUser; + } + + public setLoggedinUser(loggedinUser:IUserProperties) { + this._loggedinUser = loggedinUser; + }; +} diff --git a/catalog-ui/src/app/ng2/shared/shared.module.ts b/catalog-ui/src/app/ng2/shared/translator/translate.module.ts index 2bc7d52ab8..feaec03bbd 100644 --- a/catalog-ui/src/app/ng2/shared/shared.module.ts +++ b/catalog-ui/src/app/ng2/shared/translator/translate.module.ts @@ -7,9 +7,9 @@ * 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. @@ -18,23 +18,15 @@ * ============LICENSE_END========================================================= */ -import { NgModule } from '@angular/core'; +import { NgModule } from '@angular/core' -import { CommonModule } from '@angular/common'; -import { RouterModule } from '@angular/router'; -import { NavbarModule } from "./navbar/navbar.module"; +import { TranslateService } from "./translate.service"; +import { TranslatePipe } from "./translate.pipe"; -@NgModule({ - declarations: [ - ], - imports: [ - CommonModule, - RouterModule, - NavbarModule - ], - exports: [ - ] +@NgModule({ + providers: [TranslateService], + declarations: [TranslatePipe], + exports: [TranslatePipe] }) - -export class SharedModule {} +export class TranslateModule { } diff --git a/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts b/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts new file mode 100644 index 0000000000..42e019829f --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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 { TranslateService, ITranslateArgs } from "./translate.service"; + + +@Pipe({ + name: 'translate', + pure: false +}) +export class TranslatePipe implements PipeTransform { + private translated:string; + private lastParams: { + phrase: string; + args: {[index: string]: any}; + language: string; + } = { + phrase: undefined, + args: undefined, + language: undefined + }; + + constructor(private translateService:TranslateService) { + } + + private shouldUpdate(curParams:{[index:string]: any}) : boolean { + return ( + curParams.language !== this.lastParams.language || + curParams.args !== this.lastParams.args || + curParams.phrase !== this.lastParams.phrase + ); + } + + public transform(phrase:string, args:ITranslateArgs, language:string=this.translateService.activeLanguage) : string { + const curParams = { phrase, args, language }; + if (this.shouldUpdate(curParams)) { + this.lastParams = curParams; + this.translated = this.translateService.translate(phrase, args, language); + console.log('*updated:', this.translated); + } + + return this.translated; + } +} diff --git a/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts b/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts new file mode 100644 index 0000000000..a1d7833062 --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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 { OpaqueToken } from "@angular/core"; + +export const TranslateServiceConfigToken = new OpaqueToken('TranslateServiceConfigToken'); + +export interface ITranslateServiceConfig { + filePrefix:string; + fileSuffix:string; + allowedLanguages:string[]; + defaultLanguage:string; +} diff --git a/catalog-ui/src/app/ng2/shared/translator/translate.service.ts b/catalog-ui/src/app/ng2/shared/translator/translate.service.ts new file mode 100644 index 0000000000..ff7c643b46 --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/translator/translate.service.ts @@ -0,0 +1,235 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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 { Injectable, Inject } from "@angular/core"; +import { Response, Http } from "@angular/http"; +import { Observable, Observer, ConnectableObservable, Subscription } from "rxjs"; +import { ITranslateServiceConfig, TranslateServiceConfigToken } from "./translate.service.config"; + +export { ITranslateServiceConfig, TranslateServiceConfigToken }; + +export interface ITranslateLanguageJson { + [index:string]: string; +} + +export interface ITranslateArgs { + [index:string]: any; +} + +export class PhraseTranslator { + private _observable:ConnectableObservable<string>; + private _observer:Observer<string>; + private _languageChangeSubscription:Subscription; + + private _phraseKey:string; + private _args:ITranslateArgs; + private _language:string; + + private _markForCheck:boolean = false; + private _lastParams: { + phraseKey: string; + args: {[index: string]: any}; + language: string; + } = { + phraseKey: undefined, + args: undefined, + language: undefined + }; + + constructor(private translateService:TranslateService) { + this._observable = Observable.create(observer => { + this._observer = observer; + this._languageChangeSubscription = this.translateService.languageChangedObservable.subscribe(language => { + // using the active language, then force update + if (!this._language) { + this.update(true); + } + }); + }).publishReplay(1).refCount(); + } + + public get observable() { + return this._observable; + } + + public destroy() { + this._observer.complete(); + this._languageChangeSubscription.unsubscribe(); + + delete this._observable; + delete this._observer; + delete this._languageChangeSubscription; + } + + public shouldUpdate() : boolean { + if (!this._markForCheck) { + return false; + } + this._markForCheck = false; + return ( + this._language !== this._lastParams.language || + this._args !== this._lastParams.args || + this._phraseKey !== this._lastParams.phraseKey + ); + } + + public update(forceUpdate:boolean=false) : void { + // only update translation when having subscriptions connected. + if (this._observer && !this._observer.closed) { + if (forceUpdate || this.shouldUpdate()) { + this._lastParams = { + phraseKey: this._phraseKey, + args: this._args, + language: this._language + }; + this._markForCheck = false; + + const translated = this.translateService.translate(this._phraseKey, this._args, this._language); + this._observer.next(translated); + } + } + } + + private _changeParam(paramKey:string, value:any, update:boolean) : void { + this[`_${paramKey}`] = value; + this._markForCheck = true; + if (update) { + this.update(); + } + } + + public changePhraseKey(phraseKey:string, update:boolean=true) : void { + this._changeParam('phraseKey', phraseKey, update); + } + + public changeArgs(args:ITranslateArgs, update:boolean=true) :void { + this._changeParam('args', args, update); + } + + public changeLangauge(language:string, update:boolean=true) :void { + this._changeParam('language', language, update); + } + + public changeParams(phraseKey:string, args:ITranslateArgs={}, language?:string, forceUpdate:boolean=false) { + this._phraseKey = phraseKey; + this._args = args; + this._language = language; + this._markForCheck = true; + this.update(forceUpdate); + } +} + + +@Injectable() +export class TranslateService { + private _activeLanguage:string; + private _languageChangedObservable:ConnectableObservable<string>; + private _languageChangedObserver:Observer<string>; + private _cacheLanguagesJsons:{[index:string]:ITranslateLanguageJson} = {}; + private _cacheLanguagesLoaders:{[index:string]:Observable<ITranslateLanguageJson>} = {}; + + constructor(@Inject(TranslateServiceConfigToken) private config:ITranslateServiceConfig, private http:Http) { + this.initLanguageObservable(); + this.loadAndActivateLanguage(this.config.defaultLanguage); + } + + public get languageChangedObservable() : Observable<string> { + return this._languageChangedObservable; + } + + public get activeLanguage() { + return this._activeLanguage; + } + + private initLanguageObservable() { + this._languageChangedObservable = ConnectableObservable.create(observer => { + this._languageChangedObserver = observer; + }).publishReplay(1); // replay last emitted change on subscribe + this._languageChangedObservable.connect(); + } + + private loadLanguageJsonFile(language:string, emitOnLoad:boolean=true) : Observable<ITranslateLanguageJson> { + if (this.config.allowedLanguages.indexOf(language) === -1) { + return Observable.throw(`Language "${language}" is not available.`); + } + + if (this._cacheLanguagesJsons[language]) { + return Observable.of(this._cacheLanguagesJsons[language]); + } + + if (!(language in this._cacheLanguagesLoaders)) { + const filePath = `${this.config.filePrefix}${language}${this.config.fileSuffix}`; + this._cacheLanguagesLoaders[language] = this.http.get(filePath) + .map<Response, ITranslateLanguageJson>(resp => resp.json()) + .catch(() => Observable.throw(`Failed to load language file for "${language}"`)) + .publish(); + (<ConnectableObservable<ITranslateLanguageJson>>this._cacheLanguagesLoaders[language]).connect(); + this._cacheLanguagesLoaders[language].subscribe(languageJson => { + this._cacheLanguagesJsons[language] = languageJson; + delete this._cacheLanguagesLoaders[language]; + if (emitOnLoad) { + this._languageChangedObserver.next(language); + } + return languageJson; + }); + } + return this._cacheLanguagesLoaders[language]; + } + + public activateLanguage(language:string) : boolean { + if (this._cacheLanguagesJsons[language]) { + if (language !== this._activeLanguage) { + this._activeLanguage = language; + this._languageChangedObserver.next(this._activeLanguage); + } + return true; + } + return false; + } + + public loadAndActivateLanguage(language:string) : Observable<ITranslateLanguageJson> { + const loadLanguageObservable = this.loadLanguageJsonFile(language, false); + loadLanguageObservable.subscribe(() => { + this.activateLanguage(language); + }, () => {}); + return loadLanguageObservable; + } + + public translate(phraseKey:string, args:ITranslateArgs={}, language:string=this._activeLanguage) : string { + const phrase:string = (this._cacheLanguagesJsons[language] || {})[phraseKey] || ''; + let translated:string; + if (typeof(phrase) === 'string') { + translated = phrase + .replace( + /(^|[^\\]|\\\\)\{\{(\w+)\}\}/g, + (m, p1, p2) => `${p1}${args[p2]||''}` + ) + .replace('\\{{', '{{') + .replace('\\\\', '\\'); + } + return translated; + } + + public createPhraseTranslator(phraseKey?:string, args?:ITranslateArgs, language?:string) : PhraseTranslator { + const phraseTranslator = new PhraseTranslator(this); + phraseTranslator.changeParams(phraseKey, args, language); + return phraseTranslator; + } +} 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 ce13a8c235..c21817c001 100644 --- a/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts +++ b/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts @@ -42,6 +42,10 @@ export function cookieServiceFactory(cacheObj: ICacheObject) { return cacheObj.get('Sdc.Services.CookieService'); } +export function stateServiceFactory(cacheObj: ICacheObject) { + return cacheObj.get('$state'); +} + export function stateParamsServiceFactory(cacheObj: ICacheObject) { return cacheObj.get('$stateParams'); } @@ -74,6 +78,12 @@ export const CookieServiceProvider = { deps: ['$injector'] }; +export const StateServiceFactory = { + provide: '$state', + useFactory: stateServiceFactory, + deps: ['$injector'] +}; + export const StateParamsServiceFactory = { provide: '$stateParams', useFactory: stateParamsServiceFactory, |