diff options
author | Tal Gitelman <tg851x@intl.att.com> | 2017-12-10 18:55:03 +0200 |
---|---|---|
committer | Tal Gitelman <tg851x@intl.att.com> | 2017-12-10 19:33:38 +0200 |
commit | 51d50f0ef642e0f996a1c8b8d2ef4838bdfec892 (patch) | |
tree | 3ac236a864d74d19b0f5c9020891a7a7e5c31b44 /catalog-ui/src/app/ng2/components | |
parent | b5cc2e0695f195716d6ccdc65e73807a6632ec70 (diff) |
Final commit to master merge from
Change-Id: Ib464f9a8828437c86fe6def8af238aaf83473507
Issue-ID: SDC-714
Signed-off-by: Tal Gitelman <tg851x@intl.att.com>
Diffstat (limited to 'catalog-ui/src/app/ng2/components')
106 files changed, 2546 insertions, 273 deletions
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/components/logic/properties-table/pipes/filterChildProperties.pipe.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/pipes/filterChildProperties.pipe.ts new file mode 100644 index 0000000000..4520469594 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/pipes/filterChildProperties.pipe.ts @@ -0,0 +1,38 @@ +/*- + * ============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 { DerivedFEProperty } from 'app/models'; + +@Pipe({ + name: 'filterChildProperties', +}) +export class FilterChildPropertiesPipe implements PipeTransform { + public transform(childProperties: Array<DerivedFEProperty>, parentId: string) { + if (!parentId || !childProperties) return childProperties; + + let validParents: Array<string> = [parentId]; + while (parentId.lastIndexOf('#') > 0) { + parentId = parentId.substring(0, parentId.lastIndexOf('#')); + validParents.push(parentId); + } + return childProperties.filter(derivedProp => validParents.indexOf(derivedProp.parentName) > -1); + } +} 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/components/ui/form-components/checkbox/checkbox.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.html new file mode 100644 index 0000000000..872bf90329 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.html @@ -0,0 +1,8 @@ +<div class="checkbox-container {{checkboxStyle}}"> + <div class="checkbox-animation"></div><!--[@checkEffect]="checked"--> + <label class="checkbox-label" > + <input type="checkbox" class="checkbox-hidden" [ngModel]="checked" (ngModelChange)="toggleState($event)" [disabled]="disabled" /> + <div class="checkbox-icon"></div> + <span *ngIf="label" class="checkbox-label-content">{{label}}</span> + </label> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.less new file mode 100644 index 0000000000..9df2680b6f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.less @@ -0,0 +1,67 @@ + @import '../../../../../../assets/styles/tlv-sprite'; +@import '../../../../../../assets/styles/sprite'; + + +.checkbox-container { + display:inline-block; + position:relative; + text-align: left; + height: 20px; + + + .checkbox-icon { + display: inline-block; + } + + .checkbox-label { + font-weight: inherit; + font-size: inherit; + } + + .checkbox-label-content { + margin-left:2px; + } + + .checkbox-icon::before { + .tlv-sprite; + background-position: -10px -60px; + width: 14px; + height: 14px; + content: ''; + display: inline-block; + margin-right: 0px; + margin-top: -2px; + vertical-align: middle; + } + + input[type=checkbox].checkbox-hidden { + width:0; + height:0; + display:none; + &:checked ~ .checkbox-icon::before{ + .sprite-new; + .filled-checkbox-icon + } + &[disabled] ~ .checkbox-icon::before { + /* TODO: add disabled styles here */ + background-image: none; + background-color: #EFEFEF; + border-radius: 2px; + border: solid #CCC 1px; + } + } + + .checkbox-animation { + background-color: #009fdb; + position: absolute; + left: 2px; + top: 4px; + width:10px; + height:10px; + border-radius: 50%; + z-index: 1; + pointer-events: none; + opacity:0; + } + +} diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts new file mode 100644 index 0000000000..c8da016174 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts @@ -0,0 +1,50 @@ +/*- + * ============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, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; +//import { trigger, state, style, transition, animate, keyframes } from '@angular/core'; + +@Component({ + selector: 'checkbox', + templateUrl: './checkbox.component.html', + styleUrls: ['./checkbox.component.less'], + encapsulation: ViewEncapsulation.None + // animations: [ + // trigger('checkEffect', [ + // state('true', style({ position: 'absolute', left: '2px', top: '5px', width: '10px', height: '10px', display: 'none', opacity: '.5' })), + // state('false', style({ left: '-18px', top: '-15px', height: '50px', width: '50px', opacity: '0' })), + // transition('1 => 0', animate('150ms ease-out')), + // transition('0 => 1', animate('150ms ease-in')) + // ]) + // ] +}) +export class CheckboxComponent { + + @Input() checkboxStyle: string; + @Input() label: string; + @Input() checked: boolean; + @Input() disabled: boolean; + @Output() checkedChange: EventEmitter<any> = new EventEmitter<any>(); + + toggleState(newValue:boolean) { + this.checkedChange.emit(newValue); + } +} + diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.module.ts b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.module.ts new file mode 100644 index 0000000000..4ac7f2d7cd --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.module.ts @@ -0,0 +1,48 @@ +/*- + * ============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 { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { BrowserModule } from '@angular/platform-browser'; +import { CheckboxComponent } from './checkbox.component'; + + +@NgModule({ + imports: [CommonModule, BrowserModule, FormsModule], + declarations: [CheckboxComponent], + bootstrap: [], + exports: [CheckboxComponent] +}) +export class CheckboxModule { } + +/** README: **/ + +/** USAGE Example: + *In page.module.ts: import CheckboxModule + *In HTML: + *<checkbox checkboxStyle="class-goes-here" [label]="'Text goes here'" [disabled]="variable-goes-here" [(checked)]="default-or-variable-goes-here" (checkedChange)="change-event-goes-here()"></checkbox> + */ + +/**STYLING: (ViewEncapsulation is set to None to allow styles to be overridden or customized) + * + * To create or override styles: + * Use /deep/ or >>> prefix to override styles via other components stylesheets + */ 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/components/ui/navbar/navbar-routes.config.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar-routes.config.ts new file mode 100644 index 0000000000..ac58cbd063 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar-routes.config.ts @@ -0,0 +1,27 @@ +/*- + * ============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 { MenuType, RouteInfo } from './navbar.metadata'; + +export const ROUTES: RouteInfo[] = [ + { path: 'page1', title: 'Logo', menuType: MenuType.BRAND }, + { path: 'page1', title: 'Page 1', menuType: MenuType.LEFT }, + { path: 'page2', title: 'Page 2', menuType: MenuType.LEFT } +]; diff --git a/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.html b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.html new file mode 100644 index 0000000000..d783be4c27 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.html @@ -0,0 +1,23 @@ +<nav class="navbar navbar-dark"> + <div class="clearfix"> + <button (click)="isCollapsed = !isCollapsed" + class="navbar-toggler pull-xs-right hidden-sm-up" type="button" + aria-controls="bd-main-nav" + aria-label="Toggle navigation"> + {{menuIcon}} + </button> + <a (click)="isCollapsed = true" class="navbar-brand hidden-sm-up" [routerLink]="[brandMenu.path]"> + {{brandMenu.title}} + </a> + </div> + <div class="navbar-toggleable-xs navbar-collapse" id="bd-main-nav" [attr.aria-expanded]="!isCollapsed" [ngClass]="{collapse: isCollapsed}"> + <ul class="nav navbar-nav"> + <li (click)="isCollapsed = true" class="nav-item" routerLinkActive="active"> + <a class="navbar-brand hidden-xs-down" [routerLink]="[brandMenu.path]">{{brandMenu.title}}</a> + </li> + <li (click)="isCollapsed = true" *ngFor="let menuItem of menuItems" class="nav-item" routerLinkActive="active" [ngClass]="getMenuItemClasses(menuItem)"> + <a class="nav-item nav-link" [routerLink]="[menuItem.path]" routerLinkActive="active">{{menuItem.title}}</a> + </li> + </ul> + </div> +</nav> diff --git a/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.less b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.less new file mode 100644 index 0000000000..3e5165b798 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.less @@ -0,0 +1,11 @@ +.active { + color: #ffffff; +} +.navbar-toggler { + border: solid 1px #cccccc; + color: #ff0000; +} +.navbar { + background-color: #0000ff; + border-radius: 0; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.ts new file mode 100644 index 0000000000..68a26c4780 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.ts @@ -0,0 +1,52 @@ +/*- + * ============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, OnInit, ViewEncapsulation} from '@angular/core'; +import { ROUTES } from './navbar-routes.config'; +import { MenuType, RouteInfo } from './navbar.metadata'; + +@Component({ + selector: 'app-navbar', + templateUrl: './navbar.component.html', + styleUrls: [ './navbar.component.less' ], + encapsulation: ViewEncapsulation.None +}) +export class NavbarComponent implements OnInit { + public menuItems: Array<RouteInfo>; + public brandMenu: RouteInfo; + isCollapsed = true; + + constructor() {} + + ngOnInit() { + this.menuItems = ROUTES.filter(menuItem => menuItem.menuType !== MenuType.BRAND); + this.brandMenu = ROUTES.filter(menuItem => menuItem.menuType === MenuType.BRAND)[0]; + } + + public get menuIcon(): string { + return this.isCollapsed ? '☰' : '✖'; + } + + public getMenuItemClasses(menuItem: any) { + return { + 'pull-xs-right': this.isCollapsed && menuItem.menuType === MenuType.RIGHT + }; + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/navbar/navbar.metadata.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.metadata.ts new file mode 100644 index 0000000000..71cc3cb59f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.metadata.ts @@ -0,0 +1,31 @@ +/*- + * ============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========================================================= + */ + +export enum MenuType { + BRAND, + LEFT, + RIGHT +} + +export interface RouteInfo { + path: string; + title: string; + menuType: MenuType; +} diff --git a/catalog-ui/src/app/ng2/components/ui/navbar/navbar.module.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.module.ts new file mode 100644 index 0000000000..4a754dfe99 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.module.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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; +import { NavbarComponent } from "./navbar.component"; + +@NgModule({ + imports: [ + RouterModule, + CommonModule + ], + declarations: [ NavbarComponent ], + exports: [ + NavbarComponent + ] +}) +export class NavbarModule {} 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/components/ui/search-bar/search-bar.component.html b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html new file mode 100644 index 0000000000..36629594b0 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html @@ -0,0 +1,5 @@ +<div class="search-bar-container {{class}}"> + <input class="search-bar-input" type="text" [placeholder]="placeholder" [(ngModel)]="searchQuery" (ngModelChange)="searchQueryChange($event)"/> + <span class="clear-search-x" *ngIf="searchQuery" (click)="clearSearchQuery()">x</span> + <button class="search-bar-button" (click)="searchButtonClick()"></button> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less new file mode 100644 index 0000000000..751fceec35 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less @@ -0,0 +1,57 @@ +.search-bar-container { + display:flex; + border-radius: 4px; + box-shadow: 0px 2px 3.88px 0.12px rgba(0, 0, 0, 0.29); + + .search-bar-input { + border: 1px solid #cdcdcd; + border-radius: 4px; + border-right:none; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + outline:none; + padding:2px 50px 2px 10px; + color: #5a5a5a; + font-size: 1em; + font-style: italic; + } + + .clear-search-x { + position:absolute; + right:40px; + top:5px; + padding: 0 5px; + + &:hover { + border-radius:2px; + background-color: #ebebeb; + cursor:pointer; + } + } + + .search-bar-button { + 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; + padding: 0; + cursor:pointer; + border:solid 1px #cdcdcd; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + + &:hover { + background-position:-126px -1275px; + } + + &:active { + background-color: rgba(31, 171, 223, 0.88); + background-position:-45px -1275px; + border-left:none; + } + &:focus { + outline:none; + } + + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.ts b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.ts new file mode 100644 index 0000000000..08bdf2030f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.ts @@ -0,0 +1,32 @@ +import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; + +@Component({ + selector: 'search-bar', + templateUrl: './search-bar.component.html', + styleUrls: ['./search-bar.component.less'], + encapsulation: ViewEncapsulation.None +}) +export class SearchBarComponent { + + @Input() placeholder: string; + @Input() class: string; + @Input() searchQuery: string; + @Output() searchChanged: EventEmitter<any> = new EventEmitter<any>(); + @Output() searchButtonClicked: EventEmitter<string> = new EventEmitter<string>(); + + searchButtonClick = (): void => { + if (this.searchQuery) { //do not allow empty search + this.searchButtonClicked.emit(this.searchQuery); + } + } + + searchQueryChange = ($event): void => { + this.searchChanged.emit($event); + } + + private clearSearchQuery = (): void => { + this.searchQuery = ""; + this.searchButtonClicked.emit(this.searchQuery); + } +} + diff --git a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html new file mode 100644 index 0000000000..c9769ba5ae --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html @@ -0,0 +1,6 @@ +<div class="search-with-autocomplete-container {{searchBarClass}}" [class.autocomplete-visible]="autoCompleteValues && autoCompleteValues.length" [class.active]="searchQuery && searchQuery.length"> + <search-bar [placeholder]="searchPlaceholder" [searchQuery]="searchQuery" (searchButtonClicked)="updateSearch($event)" (searchChanged)="searchChange($event)"></search-bar> + <div class="autocomplete-results"> + <div *ngFor="let item of autoCompleteValues" class="autocomplete-result-item" (click)="updateSearch(item)">{{item}}</div> + </div> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less new file mode 100644 index 0000000000..f1830846d3 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less @@ -0,0 +1,34 @@ +.search-with-autocomplete-container{ + &.autocomplete-visible { + + .search-bar-input { + border-bottom-left-radius: 0; + } + .search-bar-button { + border-bottom-right-radius: 0; + } + .autocomplete-results { + border: solid 1px #d2d2d2; + border-top:none; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + background-color: #fff; + padding: 10px 20px; + width:100%; + position:absolute; + max-height: 200px; + overflow-y: scroll; + } + + .autocomplete-result-item { + color:#5a5a5a; + padding: 5px 0; + cursor:pointer; + + &:hover { + color: #999; + } + } + } +} + diff --git a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.ts b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.ts new file mode 100644 index 0000000000..ced056d1fc --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.ts @@ -0,0 +1,30 @@ +import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; +import { SearchBarComponent } from '../search-bar/search-bar.component'; + +@Component({ + selector: 'search-with-autocomplete', + templateUrl: './search-with-autocomplete.component.html', + styleUrls: ['./search-with-autocomplete.component.less'], + encapsulation: ViewEncapsulation.None +}) +export class SearchWithAutoCompleteComponent { + + @Input() searchPlaceholder: string; + @Input() searchBarClass: string; + @Input() searchQuery: string; + @Input() autoCompleteValues: Array<string>; + @Output() searchChanged: EventEmitter<any> = new EventEmitter<any>(); + @Output() searchButtonClicked: EventEmitter<string> = new EventEmitter<string>(); + + searchChange = (searchTerm: string) => { + this.searchQuery = searchTerm; + this.searchChanged.emit(searchTerm); + } + + updateSearch = (searchTerm: string) => { + this.searchQuery = searchTerm; + this.searchButtonClicked.emit(searchTerm); + this.autoCompleteValues = []; + } +} + diff --git a/catalog-ui/src/app/ng2/components/ui/tabs/tab/tab.component.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tab/tab.component.ts new file mode 100644 index 0000000000..bad7b80a51 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tab/tab.component.ts @@ -0,0 +1,38 @@ +/*- + * ============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'; +import { ViewEncapsulation } from '@angular/core'; + +@Component({ + selector: 'tab', + template: ` + <div *ngIf="active" class="tab-content"> + <ng-content></ng-content> + </div> + `, + encapsulation: ViewEncapsulation.None +}) +export class Tab { + @Input('tabTitle') title: string; + @Input() active:boolean = false; + @Input() indication?: number; + +} diff --git a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.html b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.html new file mode 100644 index 0000000000..57cf5d46c9 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.html @@ -0,0 +1,9 @@ +<div class="tabs {{tabStyle}}"> + <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> +</div> +<div class="tab-content-container"> + <ng-content></ng-content> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.less b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.less new file mode 100644 index 0000000000..f7b18b1cc8 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.less @@ -0,0 +1,85 @@ +@import '../../../../../assets/styles/variables'; + +tab { + height: 100%; +} + +.tabs { + display:flex; + flex: 0 0 auto; + flex-direction:row; +} + +.tab { + flex: 1 0 auto; + cursor: pointer; + padding: .5em; +} + +.tab-content-container { + flex: 1; + width:100%; + overflow-y:hidden; + overflow-x:hidden; +} + +.tab-content { + height:100%; +} + +/*Tab styles*/ +.tabs{ + &.round-tabs .tab{ + background-color: #f8f8f8; + color: #959595; + border: solid 1px #d2d2d2; + border-bottom:none; + border-left:none; + position:relative; + + &:first-child { + border-left:solid 1px #d2d2d2; + } + + &.active { + background-color:#009fdb; + color:#e9e9e9; + border-color:#009fdb; + } + + .tab-indication { + position: absolute; + top: -10px; + background-color: #009fdb; + right: 10px; + padding: 2px 0; + border-radius: 15px; + border: solid 1px #d2d2d2; + color:white; + width: 25px; + height: 25px; + text-align: center; + + } + } + + &.simple-tabs .tab { + font-size: 12px; + color: @main_color_n; + + &:after { + display:block; + content: ''; + border-bottom: 2px solid @main_color_a; + transform: scaleX(0); + transition: transform 200ms ease-in-out; + } + + &.active { + color: @main_color_a; + &:after { + transform: scaleX(1.2); + } + } + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts new file mode 100644 index 0000000000..21d2bbad43 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts @@ -0,0 +1,78 @@ +/*- + * ============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, ContentChildren, QueryList, AfterContentInit, Input, Output, EventEmitter } from '@angular/core'; +import { Tab } from './tab/tab.component'; +import { ViewEncapsulation } from '@angular/core'; +import { trigger, state, style, transition, animate, keyframes } from '@angular/core'; + +@Component({ + selector: 'tabs', + templateUrl: './tabs.component.html', + styleUrls: ['./tabs.component.less'], + encapsulation: ViewEncapsulation.None, + animations: [ + trigger('indicatorAnimation', [ + transition(':enter', [style({ transform: 'translateY(-50%)', opacity: 0 }), animate('250ms', style({ transform: 'translateY(0)', opacity: 1 })) ]), + transition(':leave', [style({ opacity: 1 }), animate('500ms', style({ opacity: 0 })) ]) + ]) + ] +}) +export class Tabs implements AfterContentInit { + + @Input() tabStyle: string; + @Input() hideIndicationOnTabChange?: boolean = false; + @ContentChildren(Tab) tabs: QueryList<Tab>; + @Output() tabChanged: EventEmitter<Tab> = new EventEmitter<Tab>(); + + + ngAfterContentInit() { + //after contentChildren are set, determine active tab. If no active tab set, activate the first one + let activeTabs = this.tabs.filter((tab) => tab.active); + + if (activeTabs.length === 0) { + this.selectTab(this.tabs.first); + } + } + + selectTab(tab: Tab) { + //activate the tab the user clicked. + this.tabs.toArray().forEach(tab => { + tab.active = false; + if (this.hideIndicationOnTabChange && tab.indication) { + tab.indication = null; + } + }); + tab.active = true; + this.tabChanged.emit(tab); + } + + triggerTabChange(tabTitle) { + this.tabs.toArray().forEach(tab => { + tab.active = (tab.title == tabTitle) ? true : false; + }); + } + + setTabIndication(tabTitle:string, indication?:number) { + let selectedTab: Tab = this.tabs.toArray().find(tab => tab.title == tabTitle); + selectedTab.indication = indication || null; + } + +} diff --git a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.module.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.module.ts new file mode 100644 index 0000000000..1300c41a90 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.module.ts @@ -0,0 +1,55 @@ +/*- + * ============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 { BrowserModule } from '@angular/platform-browser' + +import { Tabs } from './tabs.component'; +import { Tab } from './tab/tab.component'; + + +@NgModule({ + imports: [BrowserModule], + declarations: [Tabs, Tab], + bootstrap: [], + exports: [Tabs, Tab] +}) +export class TabModule { } + +/** README: **/ + +/** USAGE Example: + *In page.module.ts: import TabModule + *In HTML: + *<tabs tabStyle="class-goes-here" (tabChanged)="tabChangedEvent($event) [hideIndicationOnTabChange]="optional-boolean"> + * <tab [tabTitle]="'Tab 1'">Content of tab 1</tab> + * <tab tabTitle="Tab 2" >Content of tab 2</tab> + * ... + *</tabs> + */ + +/**STYLING: (ViewEncapsulation is set to None to allow styles to be overridden or customized) + * Existing options: + * tabStyle="round-tabs" will provide generic rounded tab look + * + * To create or override styles: + * Parent div has class ".tabs". Each tab has class ".tab". Active tab has class ".active". + * Use /deep/ or >>> prefix to override styles via other components stylesheets + */ 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 {} |