summaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/ng2/components/layout
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/ng2/components/layout')
-rw-r--r--catalog-ui/src/app/ng2/components/layout/layout.module.ts24
-rw-r--r--catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html53
-rw-r--r--catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less225
-rw-r--r--catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts149
4 files changed, 451 insertions, 0 deletions
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);
+ }
+ }
+}