summaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/ng2/components/ui
diff options
context:
space:
mode:
authorTal Gitelman <tg851x@intl.att.com>2017-12-10 18:55:03 +0200
committerTal Gitelman <tg851x@intl.att.com>2017-12-10 19:33:38 +0200
commit51d50f0ef642e0f996a1c8b8d2ef4838bdfec892 (patch)
tree3ac236a864d74d19b0f5c9020891a7a7e5c31b44 /catalog-ui/src/app/ng2/components/ui
parentb5cc2e0695f195716d6ccdc65e73807a6632ec70 (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/ui')
-rw-r--r--catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.less3
-rw-r--r--catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts140
-rw-r--r--catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts43
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.html8
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.less67
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts50
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.module.ts48
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html3
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.less11
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts51
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts42
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html14
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.less17
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts41
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html14
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.less17
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts41
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.html26
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.less36
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts57
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-button.component.less42
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.html8
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts29
-rw-r--r--catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts55
-rw-r--r--catalog-ui/src/app/ng2/components/ui/loader/loader.component.html6
-rw-r--r--catalog-ui/src/app/ng2/components/ui/loader/loader.component.less91
-rw-r--r--catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts86
-rw-r--r--catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.html3
-rw-r--r--catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.less13
-rw-r--r--catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts44
-rw-r--r--catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.html9
-rw-r--r--catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.less13
-rw-r--r--catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts70
-rw-r--r--catalog-ui/src/app/ng2/components/ui/menu/menu-list.module.ts27
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.html5
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.ts38
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal/modal.component.html21
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal/modal.component.less129
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts62
-rw-r--r--catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts22
-rw-r--r--catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component.ts10
-rw-r--r--catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.html57
-rw-r--r--catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.less90
-rw-r--r--catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts78
-rw-r--r--catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts22
-rw-r--r--catalog-ui/src/app/ng2/components/ui/navbar/navbar-routes.config.ts27
-rw-r--r--catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.html23
-rw-r--r--catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.less11
-rw-r--r--catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.ts52
-rw-r--r--catalog-ui/src/app/ng2/components/ui/navbar/navbar.metadata.ts31
-rw-r--r--catalog-ui/src/app/ng2/components/ui/navbar/navbar.module.ts36
-rw-r--r--catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html24
-rw-r--r--catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.less77
-rw-r--r--catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts278
-rw-r--r--catalog-ui/src/app/ng2/components/ui/popover/popover.component.ts179
-rw-r--r--catalog-ui/src/app/ng2/components/ui/popover/popover.module.ts45
-rw-r--r--catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html5
-rw-r--r--catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less57
-rw-r--r--catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.ts32
-rw-r--r--catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html6
-rw-r--r--catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less34
-rw-r--r--catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.ts30
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tabs/tab/tab.component.ts38
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.html9
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.less85
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts78
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tabs/tabs.module.ts55
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.html12
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.less11
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.ts215
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.component.ts109
-rw-r--r--catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.module.ts44
-rw-r--r--catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts80
73 files changed, 3442 insertions, 0 deletions
diff --git a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.less b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.less
new file mode 100644
index 0000000000..e219d49aa4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.less
@@ -0,0 +1,3 @@
+dynamic-element {
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts
new file mode 100644
index 0000000000..53d1590b1c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts
@@ -0,0 +1,140 @@
+/*-
+ * ============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, Compiler, EventEmitter, ViewContainerRef, ViewChild, Input, Output, ElementRef, ComponentRef, ComponentFactoryResolver } from '@angular/core'
+import {ValidationConfiguration} from "app/models";
+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',
+ template: `<div #target></div>`,
+ styleUrls: ['./dynamic-element.component.less'],
+ entryComponents: [
+ UiElementInputComponent,
+ UiElementDropDownComponent,
+ UiElementPopoverInputComponent,
+ UiElementIntegerInputComponent
+ ]
+})
+export class DynamicElementComponent {
+
+ @ViewChild('target', { read: ViewContainerRef }) target: any;
+ @Input() type: any;
+ @Input() name: string;
+ @Input() readonly:boolean;
+ @Input() path:string;//optional param. used only for for subnetpoolid type
+ value:any;
+
+ // Two way binding for value (need to write the "Change" word like this)
+ @Output('valueChange') emitter: EventEmitter<string> = new EventEmitter<any>();
+ @Input('value') set setValueValue(value) {
+ this.value = value;
+ }
+
+ cmpRef: ComponentRef<any>;
+ private isViewInitialized: boolean = false;
+ validation = ValidationConfiguration.validation;
+
+ constructor(
+ private componentFactoryResolver: ComponentFactoryResolver,
+ private compiler: Compiler,
+ private el: ElementRef) {
+ }
+
+ updateComponent() {
+ if (!this.isViewInitialized) {
+ return;
+ }
+ if (this.cmpRef) {
+ this.cmpRef.destroy();
+ }
+
+ // Factory to create component based on type or peroperty name.
+ 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 PROPERTY_DATA.SCALAR_TYPES.indexOf(this.type) > -1:
+ case this.type == 'string':
+ this.createComponent(UiElementInputComponent);
+ break;
+ 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'));
+ this.cmpRef.instance.values = tmp;
+ break;
+ default:
+ this.createComponent(UiElementInputComponent);
+ console.log("ERROR: No ui component to handle type: " + this.type);
+ }
+
+ // Additional attributes in base element class
+ if (this.cmpRef) {
+ this.cmpRef.instance.name = this.name;
+ this.cmpRef.instance.type = this.type;
+ this.cmpRef.instance.value = this.value;
+ this.cmpRef.instance.readonly = this.readonly;
+ }
+
+ // Subscribe to change event of of ui-element-basic and fire event to change the value
+ this.cmpRef.instance.baseEmitter.subscribe((value):void => {
+ this.emitter.emit(value)
+ });
+
+ }
+
+ createComponent(ComponentToCreate:any):void {
+ let factory = this.componentFactoryResolver.resolveComponentFactory(ComponentToCreate);
+ this.cmpRef = this.target.createComponent(factory);
+ }
+
+ ngOnChanges() {
+ this.updateComponent();
+ }
+
+ ngAfterContentInit() {
+ this.isViewInitialized = true;
+ this.updateComponent();
+ }
+
+ ngOnDestroy() {
+ if (this.cmpRef) {
+ this.cmpRef.destroy();
+ }
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts
new file mode 100644
index 0000000000..50b22505a9
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts
@@ -0,0 +1,43 @@
+/*-
+ * ============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 {PopoverModule} from "../popover/popover.module";
+import {TooltipModule} from "../tooltip/tooltip.module";
+import {DynamicElementComponent} from "./dynamic-element.component";
+import {FormElementsModule} from "../form-components/form-elements.module";
+
+@NgModule({
+ declarations: [
+ DynamicElementComponent,
+ ],
+ imports: [
+ PopoverModule,
+ TooltipModule,
+ FormElementsModule
+ ],
+ exports: [
+ DynamicElementComponent
+ ],
+ providers: []
+})
+export class DynamicElementModule {
+
+}
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/ui/form-components/dropdown/ui-element-dropdown.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.less
new file mode 100644
index 0000000000..ea3e35140e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.less
@@ -0,0 +1,11 @@
+@import '../../../../../../assets/styles/variables';
+
+/deep/ ui-element-dropdown {
+
+ select {
+ text-indent: 6px;
+ border: solid 1px @main_color_o;
+ width: 100%;
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts
new file mode 100644
index 0000000000..5abf32c61b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts
@@ -0,0 +1,51 @@
+/*-
+ * ============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, EventEmitter, Output, Input} from '@angular/core'
+import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.component';
+
+export class DropdownValue {
+ value:any;
+ label:string;
+
+ constructor(value:any,label:string) {
+ this.value = value;
+ this.label = label;
+ }
+}
+
+@Component({
+ selector: 'ui-element-dropdown',
+ templateUrl: './ui-element-dropdown.component.html',
+ styleUrls: ['./ui-element-dropdown.component.less'],
+})
+export class UiElementDropDownComponent extends UiElementBase implements UiElementBaseInterface {
+ @Input()
+ values: DropdownValue[]|string[];
+
+ constructor() {
+ super();
+ }
+
+ onSave() {
+ 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/ui/form-components/input/ui-element-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html
new file mode 100644
index 0000000000..b7d7c859c7
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html
@@ -0,0 +1,14 @@
+<input
+ class="value-input"
+ [ngClass]="{'error': control.invalid, 'disabled':readonly}"
+ type="text"
+ [name]="name"
+ [(ngModel)]="value"
+ (change)="onSave()"
+ [attr.maxlength]="validation.propertyValue.max"
+ [attr.minlength]="validation.propertyValue.min"
+ [pattern]="pattern"
+ [formControl]="control"
+ tooltip="{{value}}"
+ [readonly]="readonly"
+ />
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.less
new file mode 100644
index 0000000000..d320c7ff8b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.less
@@ -0,0 +1,17 @@
+@import '../../../../../../assets/styles/variables';
+
+/deep/ ui-element-input {
+
+ input {
+ text-indent: 6px;
+ border: solid 1px @main_color_o;
+ }
+
+ .error {
+ border: solid 1px @func_color_q;
+ color: @func_color_q;
+ outline: none;
+ box-sizing: border-box;
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts
new file mode 100644
index 0000000000..fb3b3db859
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts
@@ -0,0 +1,41 @@
+/*-
+ * ============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, ViewChild, ElementRef, ContentChildren, Input} from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser'
+import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.component';
+
+@Component({
+ selector: 'ui-element-input',
+ templateUrl: './ui-element-input.component.html',
+ styleUrls: ['./ui-element-input.component.less'],
+})
+export class UiElementInputComponent extends UiElementBase implements UiElementBaseInterface {
+ constructor() {
+ super();
+ this.pattern = this.validation.validationPatterns.comment;
+ }
+
+ onSave() {
+ if (!this.control.invalid){
+ this.baseEmitter.emit(this.value);
+ }
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/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
new file mode 100644
index 0000000000..9fbc9e1094
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html
@@ -0,0 +1,14 @@
+<input
+ class="value-input"
+ [ngClass]="{'error': control.invalid, 'disabled':readonly}"
+ type="text"
+ [name]="name"
+ [(ngModel)]="value"
+ (change)="onSave()"
+ [attr.maxlength]="validation.propertyValue.max"
+ [attr.minlength]="validation.propertyValue.min"
+ [pattern]="pattern"
+ [formControl]="control"
+ tooltip="{{value}}"
+ [readonly]="readonly"
+/>
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/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
new file mode 100644
index 0000000000..8073c3858e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.less
@@ -0,0 +1,17 @@
+@import '../../../../../../assets/styles/variables';
+
+/deep/ ui-element-integer-input {
+
+ input {
+ text-indent: 6px;
+ border: solid 1px @main_color_o;
+ }
+
+ .error {
+ border: solid 1px @func_color_q;
+ color: @func_color_q;
+ outline: none;
+ box-sizing: border-box;
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/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
new file mode 100644
index 0000000000..1667f4393d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts
@@ -0,0 +1,41 @@
+/*-
+ * ============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, ViewChild, ElementRef, ContentChildren, Input} from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser'
+import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.component';
+
+@Component({
+ selector: 'ui-element-integer-input',
+ templateUrl: './ui-element-integer-input.component.html',
+ styleUrls: ['./ui-element-integer-input.component.less'],
+})
+export class UiElementIntegerInputComponent extends UiElementBase implements UiElementBaseInterface {
+ constructor() {
+ super();
+ //this.pattern = this.validation.validationPatterns.comment;
+ }
+
+ onSave() {
+ if (!this.control.invalid){
+ this.baseEmitter.emit(this.value ? JSON.parse(this.value) : this.value);
+ }
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/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
new file mode 100644
index 0000000000..3bd51b4e36
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.html
@@ -0,0 +1,26 @@
+<div class="popover-input-wrapper" tooltip="{{value}}">
+ <input
+ class="value-input"
+ type="text"
+ [ngClass]="{'error': control.invalid}"
+ [name]="name"
+ [value]="value!=undefined?value:''"
+ disabled
+ />
+ <button [popover]="popoverForm" [ngClass]="{'disabled':readonly}">Edit</button>
+</div>
+
+<popover-content #popoverForm [title]="name" [buttons]="buttonsArray" [placement]="'top'" [closeOnClickOutside]="true">
+ <div class="edit-subnet-wrapper">
+ <textarea rows="5"
+ #textArea
+ class="subnet-value"
+ [ngClass]="{'error': control.invalid}"
+ [(ngModel)]="value"
+ [attr.maxlength]="validation.propertyValue.max"
+ [attr.minlength]="validation.propertyValue.min"
+ [pattern]="pattern"
+ [formControl]="control"
+ ></textarea>
+ </div>
+</popover-content>
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/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
new file mode 100644
index 0000000000..5be443f7b6
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.less
@@ -0,0 +1,36 @@
+@import '../../../../../../assets/styles/variables';
+
+.popover-input-wrapper {
+ display: flex;
+}
+
+/deep/ ui-element-popover-input {
+
+ .popover {
+ max-width: 350px;
+ width: 350px;
+ }
+
+ .edit-subnet-wrapper {
+ padding: 12px;
+
+ .subnet-value {
+ width: 100%;
+ resize: none;
+ }
+ }
+
+ input {
+ padding-right: 6px;
+ padding-left: 6px;
+ border: solid 1px @main_color_o;
+ }
+
+ .error {
+ border: solid 1px @func_color_q;
+ color: @func_color_q;
+ outline: none;
+ box-sizing: border-box;
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/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
new file mode 100644
index 0000000000..61688df3f0
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts
@@ -0,0 +1,57 @@
+/*-
+ * ============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, ViewChild, ElementRef, Input} from '@angular/core';
+import {ButtonsModelMap, ButtonModel} from "app/models";
+import {PopoverContentComponent} from "../../popover/popover-content.component";
+import {UiElementBase, UiElementBaseInterface} from "../ui-element-base.component";
+
+@Component({
+ selector: 'ui-element-popover-input',
+ templateUrl: './ui-element-popover-input.component.html',
+ styleUrls: ['./ui-element-popover-input.component.less']
+})
+export class UiElementPopoverInputComponent extends UiElementBase implements UiElementBaseInterface {
+ @ViewChild('textArea') textArea: ElementRef;
+ @ViewChild('popoverForm') popoverContentComponent: PopoverContentComponent;
+
+ saveButton: ButtonModel;
+ buttonsArray: ButtonsModelMap;
+
+ onSave = ():void => {
+ if (!this.control.invalid){
+ this.baseEmitter.emit(this.value);
+ this.popoverContentComponent.hide();
+ }
+ }
+
+ constructor() {
+ super();
+ // Create Save button and insert to buttons map
+ this.saveButton = new ButtonModel('save', 'blue', this.onSave);
+ this.buttonsArray = { 'test': this.saveButton };
+
+ // Define the regex pattern for this controller
+ this.pattern = this.validation.validationPatterns.comment;
+
+ // Disable / Enable button according to validation
+ //this.control.valueChanges.subscribe(data => this.saveButton.disabled = this.control.invalid);
+ }
+}
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/ui/form-components/ui-element-base.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts
new file mode 100644
index 0000000000..ae2013ff70
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.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 { Component, EventEmitter, Input, Output } from '@angular/core'
+import { ValidationConfiguration } from "app/models";
+import { FormControl, Validators } from '@angular/forms';
+
+export interface UiElementBaseInterface {
+ onSave();
+}
+
+@Component({
+ template: ``,
+ styles: []
+})
+export class UiElementBase {
+
+ protected validation = ValidationConfiguration.validation;
+ protected control: FormControl;
+
+ // Two way binding for value (need to write the "Change" word like this)
+ @Output('valueChange') baseEmitter: EventEmitter<string> = new EventEmitter<any>();
+ @Input('value') set setValueValue(value) {
+ this.value = value;
+ }
+
+ @Input() name: string;
+ @Input() type: string;
+ @Input() value: any;
+ @Input() pattern: any;
+ @Input() readonly:boolean;
+
+ constructor() {
+ //this.control = new FormControl('', [Validators.required]);
+ this.control = new FormControl('', []);
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html
new file mode 100644
index 0000000000..a62aa114d9
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html
@@ -0,0 +1,6 @@
+<div *ngIf="isVisible" data-tests-id="tlv-loader" [ngClass]="relative ? 'loader-relative' : 'loader-fixed'"
+ [style.top]="offset.top" [style.left]="offset.left" [style.width]="offset.width" [style.height]="offset.height">
+ <div class="tlv-loader-back" [ngClass]="{'tlv-loader-relative':relative}"></div>
+ <div class="tlv-loader {{size}}"></div>
+</div>
+
diff --git a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.less b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.less
new file mode 100644
index 0000000000..006c3bfa43
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.less
@@ -0,0 +1,91 @@
+@import '../../../../../assets/styles/variables';
+.tlv-loader-back {
+ background-color: @main_color_p;
+ position: fixed;
+ top: 50px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 9999;
+ opacity: 0.5;
+}
+
+.tlv-loader-relative { position: absolute; top: 0;}
+
+.tlv-loader {
+ z-index: 10002;
+}
+
+.loader-relative {
+ display: block;
+ position:absolute;
+ width: 100%;
+ height:100%;
+}
+
+.loader-fixed {
+ display: block;
+ position:fixed;
+ top:0;
+ left:0;
+ width: 100%;
+ height:100%;
+}
+
+@keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 0.8; }
+}
+
+/* Firefox < 16 */
+@-moz-keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 0.8; }
+}
+
+/* Safari, Chrome and Opera > 12.1 */
+@-webkit-keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 0.8; }
+}
+
+/* Internet Explorer */
+@-ms-keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 0.8; }
+}
+
+/* Opera < 12.1 */
+@-o-keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 0.8; }
+}
+
+@keyframes fadeout {
+ from { opacity: 0.8; }
+ to { opacity: 0; }
+}
+
+/* Firefox < 16 */
+@-moz-keyframes fadeout {
+ from { opacity: 0.8; }
+ to { opacity: 0; }
+}
+
+/* Safari, Chrome and Opera > 12.1 */
+@-webkit-keyframes fadeout {
+ from { opacity: 0.8; }
+ to { opacity: 0; }
+}
+
+/* Internet Explorer */
+@-ms-keyframes fadeout {
+ from { opacity: 0.8; }
+ to { opacity: 0; }
+}
+
+/* Opera < 12.1 */
+@-o-keyframes fadeout {
+ from { opacity: 0.8; }
+ to { opacity: 0; }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts
new file mode 100644
index 0000000000..f66aa551e2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts
@@ -0,0 +1,86 @@
+/*-
+ * ============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=========================================================
+ */
+
+/**
+ * Created by rc2122 on 6/6/2017.
+ */
+import { Component, Input, ViewContainerRef, SimpleChanges} from "@angular/core";
+@Component({
+ selector: 'loader',
+ templateUrl: './loader.component.html',
+ styleUrls: ['./loader.component.less']
+})
+export class LoaderComponent {
+
+ @Input() display: boolean;
+ @Input() size: string;// small || medium || large
+ @Input() relative: boolean; // If is relative is set to true, loader will appear over parent element. Otherwise, will be fixed over the entire page.
+ @Input() loaderDelay: number; //optional - number of ms to delay loader display.
+
+ private isVisible: boolean = false;
+ private offset : {
+ top: string;
+ left: string;
+ width: string;
+ height: string;
+ };
+
+ constructor(private viewContainerRef: ViewContainerRef) {
+ }
+
+ ngOnInit() {
+ if (!this.size) {
+ this.size = 'large';
+ }
+ if (this.display === true) {
+ this.changeLoaderDisplay(true);
+ }
+ }
+
+ ngOnChanges(changes: SimpleChanges) {
+ if(changes.display){
+ this.changeLoaderDisplay(this.display);
+ }
+ }
+
+ private changeLoaderDisplay = (display: boolean): void => {
+ if (display) {
+ window.setTimeout((): void => {
+ this.display && this.showLoader(); //only show loader if this.display has not changed in the meanwhile.
+ }, this.loaderDelay || 0);
+ } else {
+ this.isVisible = false;
+ }
+ }
+
+ private showLoader = () => {
+ if (this.relative === true) {
+ let parentElement = this.viewContainerRef.element.nativeElement.parentElement;
+ this.offset = {
+ left: (parentElement.offsetLeft) ? parentElement.offsetLeft + "px" : undefined,
+ top: (parentElement.offsetTop) ? parentElement.offsetTop + "px" : undefined,
+ width: (parentElement.offsetWidth) ? parentElement.offsetWidth + "px" : undefined,
+ height: (parentElement.offsetHeight) ? parentElement.offsetHeight + "px" : undefined
+ };
+ }
+ this.isVisible = true;
+ }
+
+}
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/ui/menu/menu-item.component.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts
new file mode 100644
index 0000000000..8b2006634e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts
@@ -0,0 +1,44 @@
+/*-
+ * ============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 } from '@angular/core';
+
+@Component({
+ selector: 'menu-item',
+ templateUrl: './menu-item.component.html',
+ styleUrls:['./menu-item.component.less']
+})
+export class MenuItemComponent {
+ @Input() action:Function;
+ @Input() styleClass:any;
+
+ public parentMenu:any;
+
+ constructor() {
+ }
+
+ 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/ui/modal/error-message/error-message.component.html b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.html
new file mode 100644
index 0000000000..433bd4fd6f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.html
@@ -0,0 +1,5 @@
+<div class="error-message-component">
+ <div>Error code: {{input.messageId}}</div>
+ <div>Status code: {{input.status}}</div>
+ <div class="error-message">{{input.message}}</div>
+</div> \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.ts
new file mode 100644
index 0000000000..c0d6673412
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.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=========================================================
+ */
+
+/**
+ * Created by ngordon on 7/30/2017.
+ */
+import { Component, Input } from '@angular/core';
+import { ServerErrorResponse } from 'app/models';
+
+@Component({
+ selector: 'error-message',
+ templateUrl: './error-message.component.html'
+})
+
+export class ErrorMessageComponent {
+ @Input() input: ServerErrorResponse;
+
+ constructor() {
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html
new file mode 100644
index 0000000000..9a0fdf6bf4
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html
@@ -0,0 +1,21 @@
+<div class="custom-modal {{input.size}}">
+ <div class="ng2-modal-content">
+ <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 *ngIf="input.content">{{input.content}}</div>
+ <div #dynamicContentContainer></div>
+ </div>
+
+ <div class="ng2-modal-footer">
+ <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>
+</div>
+<div class="modal-background"></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/ui/modal/modal.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts
new file mode 100644
index 0000000000..89db8d1140
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Created by rc2122 on 6/1/2017.
+ */
+import { Component, ElementRef, Input, OnInit, OnDestroy } from '@angular/core';
+import {ViewContainerRef, ViewChild} from '@angular/core';
+import * as $ from 'jquery';
+import { ButtonsModelMap, ModalModel } from 'app/models';
+
+@Component({
+ selector: 'modal',
+ templateUrl: './modal.component.html',
+ styleUrls:['modal.component.less']
+})
+
+export class ModalComponent implements OnInit, OnDestroy {
+ @Input() input: ModalModel;
+ @Input() dynamicContent: any;
+ @ViewChild('dynamicContentContainer', { read: ViewContainerRef }) dynamicContentContainer: ViewContainerRef; //Allows for custom component as body instead of simple message. See ModalService.createActionModal for implementation details, and HttpService's catchError() for example.
+ private modalElement: JQuery;
+
+ constructor( el: ElementRef ) {
+ this.modalElement = $(el.nativeElement);
+ }
+
+ ngOnInit(): void {
+ this.modalElement.appendTo('body');
+ }
+
+ ngOnDestroy(): void {
+ this.modalElement.remove();
+ }
+
+ open(): void {
+ this.modalElement.show();
+ $('body').addClass('modal-open');
+ }
+
+ close(): void {
+ this.modalElement.hide();
+ $('body').removeClass('modal-open');
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts
new file mode 100644
index 0000000000..c38e60194b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts
@@ -0,0 +1,22 @@
+import { NgModule } from "@angular/core";
+import { CommonModule } from '@angular/common';
+import { ModalService } from 'app/ng2/services/modal.service';
+import { ErrorMessageComponent } from "./error-message/error-message.component";
+import {ModalComponent} from "./modal.component";
+
+@NgModule({
+ declarations: [
+ ModalComponent,
+ ErrorMessageComponent
+ ],
+ imports: [CommonModule],
+ exports: [ModalComponent, ErrorMessageComponent],
+ entryComponents: [ //need to add anything that will be dynamically created
+ ModalComponent,
+ ErrorMessageComponent
+ ],
+ providers: [ModalService]
+})
+export class ModalModule {
+
+} \ No newline at end of file
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/ui/popover/popover-content.component.html b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html
new file mode 100644
index 0000000000..6d76f0ad06
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html
@@ -0,0 +1,24 @@
+<div #popoverDiv class="popover {{ effectivePlacement }}"
+ [style.top]="top + 'px'"
+ [style.left]="left + 'px'"
+ [class.in]="isIn"
+ [class.fade]="animation"
+ style="display: block"
+ role="popover"
+ [ngClass]="{'hide-arrow':hideArrow}">
+ <div [hidden]="!closeOnMouseOutside" class="virtual-area"></div>
+ <div class="arrow" *ngIf="!hideArrow"></div>
+ <div class="popover-header">
+ <span class="title">{{ title }}</span>
+ <span class="close-button" (click)="popover.hide()"></span>
+ </div>
+ <ng-content></ng-content>
+ <div class="popover-footer">
+ <button *ngFor="let buttonName of buttonsNames"
+ class="tlv-btn {{buttons[buttonName].cssClass}}"
+ [disabled] = "buttons[buttonName].getDisabled && buttons[buttonName].getDisabled()"
+ (click) = "buttons[buttonName].callback()">{{buttons[buttonName].text}}</button>
+ </div>
+</div>
+
+
diff --git a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.less b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.less
new file mode 100644
index 0000000000..fbdec0b16b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.less
@@ -0,0 +1,77 @@
+@import '../../../../../assets/styles/variables';
+@import '../../../../../assets/styles/mixins';
+@import '../../../../../assets/styles/sprite-old';
+.popover .virtual-area {
+ height: 11px;
+ width: 100%;
+ position: absolute;
+}
+.popover.top .virtual-area {
+ bottom: -11px;
+}
+.popover.bottom .virtual-area {
+ top: -11px;
+}
+.popover.left .virtual-area {
+ right: -11px;
+}
+.popover.right .virtual-area {
+ left: -11px;
+}
+.popover.hide-arrow{
+ margin: 0;
+}
+
+.popover-header{
+ .m_14_m;
+ font-weight: bold;
+ -webkit-box-flex: 1;
+ -ms-flex-positive: 1;
+ flex-grow: 1;
+ height: 40px;
+ line-height: 48px;
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ text-align: left;
+ border-bottom: solid 1px @main_color_o;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ margin: 0px 20px;
+ max-width:350px;
+
+ .title{
+ flex: 1;
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ .close-button{
+ .sprite;
+ .sprite.x-btn-black;
+ cursor: pointer;
+ }
+}
+
+.popover-footer{
+ background-color: @tlv_color_t;
+ height: 40px;
+ 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;
+ button{
+ margin: 8px 12px 8px 6px;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts
new file mode 100644
index 0000000000..6eb36287d0
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts
@@ -0,0 +1,278 @@
+/*-
+ * ============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, AfterViewInit, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, EventEmitter, Renderer } from "@angular/core";
+import {ButtonsModelMap} from "app/models";
+import {PopoverComponent} from "./popover.component";
+
+@Component({
+ selector: "popover-content",
+ templateUrl:'./popover-content.component.html',
+ styleUrls:['popover-content.component.less']
+})
+export class PopoverContentComponent implements AfterViewInit, OnDestroy {
+
+ @Input() public title: string;
+ @Input() public buttons:ButtonsModelMap;
+
+ @Input()
+ content: string;
+
+ @Input()
+ placement: "top"|"bottom"|"left"|"right"|"auto"|"auto top"|"auto bottom"|"auto left"|"auto right" = "bottom";
+
+ @Input()
+ animation: boolean = true;
+
+ @Input()
+ closeOnClickOutside: boolean = false;
+
+ @Input()
+ closeOnMouseOutside: boolean = false;
+
+ @Input()
+ hideArrow: boolean = false;
+
+ @ViewChild("popoverDiv")
+ popoverDiv: ElementRef;
+
+ buttonsNames:Array<string>;
+
+ popover: PopoverComponent;
+ onCloseFromOutside = new EventEmitter();
+ top: number = -10000;
+ left: number = -10000;
+ isIn: boolean = false;
+ displayType: string = "none";
+ effectivePlacement: string;
+
+ onDocumentMouseDown = (event: any) => {
+ const element = this.element.nativeElement;
+ if (!element || !this.popover) return;
+ if (element.contains(event.target) || this.popover.getElement().contains(event.target)) return;
+ this.hide();
+ this.onCloseFromOutside.emit(undefined);
+ };
+
+
+ constructor(protected element: ElementRef,
+ protected cdr: ChangeDetectorRef,
+ protected renderer: Renderer) {
+ }
+
+ listenClickFunc: any;
+ listenMouseFunc: any;
+
+ ngAfterViewInit(): void {
+ this.buttonsNames = Object.keys(this.buttons);
+ if (this.closeOnClickOutside)
+ this.listenClickFunc = this.renderer.listenGlobal("document", "mousedown", (event: any) => this.onDocumentMouseDown(event));
+ if (this.closeOnMouseOutside)
+ this.listenMouseFunc = this.renderer.listenGlobal("document", "mouseover", (event: any) => this.onDocumentMouseDown(event));
+
+ this.show();
+ this.cdr.detectChanges();
+ }
+
+ ngOnDestroy() {
+ if (this.closeOnClickOutside)
+ this.listenClickFunc();
+ if (this.closeOnMouseOutside)
+ this.listenMouseFunc();
+ }
+
+ // -------------------------------------------------------------------------
+ // Public Methods
+ // -------------------------------------------------------------------------
+
+ show(): void {
+ if (!this.popover || !this.popover.getElement())
+ return;
+
+ const p = this.positionElements(this.popover.getElement(), this.popoverDiv.nativeElement, this.placement);
+ this.displayType = "block";
+ this.top = p.top;
+ this.left = p.left;
+ this.isIn = true;
+ }
+
+ hide(): void {
+ this.top = -10000;
+ this.left = -10000;
+ this.isIn = true;
+ this.popover.hide();
+ }
+
+ hideFromPopover() {
+ this.top = -10000;
+ this.left = -10000;
+ this.isIn = true;
+ }
+
+ // -------------------------------------------------------------------------
+ // Protected Methods
+ // -------------------------------------------------------------------------
+
+ protected positionElements(hostEl: HTMLElement, targetEl: HTMLElement, positionStr: string, appendToBody: boolean = false): { top: number, left: number } {
+ let positionStrParts = positionStr.split("-");
+ let pos0 = positionStrParts[0];
+ let pos1 = positionStrParts[1] || "center";
+ let hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl);
+ let targetElWidth = targetEl.offsetWidth;
+ let targetElHeight = targetEl.offsetHeight;
+
+ this.effectivePlacement = pos0 = this.getEffectivePlacement(pos0, hostEl, targetEl);
+
+ let shiftWidth: any = {
+ center: function (): number {
+ return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;
+ },
+ left: function (): number {
+ return hostElPos.left;
+ },
+ right: function (): number {
+ return hostElPos.left + hostElPos.width - targetElWidth;
+ }
+ };
+
+ let shiftHeight: any = {
+ center: function (): number {
+ return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;
+ },
+ top: function (): number {
+ return hostElPos.top;
+ },
+ bottom: function (): number {
+ return hostElPos.top + hostElPos.height - targetElHeight;
+ }
+ };
+
+ let targetElPos: { top: number, left: number };
+ switch (pos0) {
+ case "right":
+ targetElPos = {
+ top: shiftHeight[pos1](),
+ left: hostElPos.left + hostElPos.width
+ };
+ break;
+
+ case "left":
+ targetElPos = {
+ top: shiftHeight[pos1](),
+ left: hostElPos.left - targetElWidth
+ };
+ break;
+
+ case "bottom":
+ targetElPos = {
+ top: hostElPos.top + hostElPos.height,
+ left: shiftWidth[pos1]()
+ };
+ break;
+
+ default:
+ targetElPos = {
+ top: hostElPos.top - targetElHeight,
+ left: shiftWidth[pos1]()
+ };
+ break;
+ }
+
+ return targetElPos;
+ }
+
+ protected position(nativeEl: HTMLElement): { width: number, height: number, top: number, left: number } {
+ let offsetParentBCR = { top: 0, left: 0 };
+ const elBCR = this.offset(nativeEl);
+ const offsetParentEl = this.parentOffsetEl(nativeEl);
+ if (offsetParentEl !== window.document) {
+ offsetParentBCR = this.offset(offsetParentEl);
+ offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
+ offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
+ }
+
+ const boundingClientRect = nativeEl.getBoundingClientRect();
+ return {
+ width: boundingClientRect.width || nativeEl.offsetWidth,
+ height: boundingClientRect.height || nativeEl.offsetHeight,
+ top: elBCR.top - offsetParentBCR.top,
+ left: elBCR.left - offsetParentBCR.left
+ };
+ }
+
+ protected offset(nativeEl: any): { width: number, height: number, top: number, left: number } {
+ const boundingClientRect = nativeEl.getBoundingClientRect();
+ return {
+ width: boundingClientRect.width || nativeEl.offsetWidth,
+ height: boundingClientRect.height || nativeEl.offsetHeight,
+ top: boundingClientRect.top + (window.pageYOffset || window.document.documentElement.scrollTop),
+ left: boundingClientRect.left + (window.pageXOffset || window.document.documentElement.scrollLeft)
+ };
+ }
+
+ protected getStyle(nativeEl: HTMLElement, cssProp: string): string {
+ if ((nativeEl as any).currentStyle) // IE
+ return (nativeEl as any).currentStyle[cssProp];
+
+ if (window.getComputedStyle)
+ return (window.getComputedStyle as any)(nativeEl)[cssProp];
+
+ // finally try and get inline style
+ return (nativeEl.style as any)[cssProp];
+ }
+
+ protected isStaticPositioned(nativeEl: HTMLElement): boolean {
+ return (this.getStyle(nativeEl, "position") || "static" ) === "static";
+ }
+
+ protected parentOffsetEl(nativeEl: HTMLElement): any {
+ let offsetParent: any = nativeEl.offsetParent || window.document;
+ while (offsetParent && offsetParent !== window.document && this.isStaticPositioned(offsetParent)) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || window.document;
+ }
+
+ protected getEffectivePlacement(placement: string, hostElement: HTMLElement, targetElement: HTMLElement): string {
+ const placementParts = placement.split(" ");
+ if (placementParts[0] !== "auto") {
+ return placement;
+ }
+
+ const hostElBoundingRect = hostElement.getBoundingClientRect();
+
+ const desiredPlacement = placementParts[1] || "bottom";
+
+ if (desiredPlacement === "top" && hostElBoundingRect.top - targetElement.offsetHeight < 0) {
+ return "bottom";
+ }
+ if (desiredPlacement === "bottom" && hostElBoundingRect.bottom + targetElement.offsetHeight > window.innerHeight) {
+ return "top";
+ }
+ if (desiredPlacement === "left" && hostElBoundingRect.left - targetElement.offsetWidth < 0) {
+ return "right";
+ }
+ if (desiredPlacement === "right" && hostElBoundingRect.right + targetElement.offsetWidth > window.innerWidth) {
+ return "left";
+ }
+
+ return desiredPlacement;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/popover/popover.component.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover.component.ts
new file mode 100644
index 0000000000..e976bc7bf2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/popover/popover.component.ts
@@ -0,0 +1,179 @@
+/*-
+ * ============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 { Directive, HostListener, ComponentRef, ViewContainerRef, ComponentFactoryResolver, ComponentFactory, Input, OnChanges, SimpleChange, Output, EventEmitter } from "@angular/core";
+import {PopoverContentComponent} from "./popover-content.component";
+
+@Directive({
+ selector: "[popover]",
+ exportAs: "popover"
+})
+export class PopoverComponent implements OnChanges {
+
+ protected PopoverComponent = PopoverContentComponent;
+ protected popover: ComponentRef<PopoverContentComponent>;
+ protected visible: boolean;
+
+
+ constructor(protected viewContainerRef: ViewContainerRef,
+ protected resolver: ComponentFactoryResolver) {
+ }
+
+ @Input("popover")
+ content: string|PopoverContentComponent;
+
+ @Input()
+ popoverDisabled: boolean;
+
+ @Input()
+ popoverAnimation: boolean;
+
+ @Input()
+ popoverPlacement: "top"|"bottom"|"left"|"right"|"auto"|"auto top"|"auto bottom"|"auto left"|"auto right";
+
+ @Input()
+ popoverTitle: string;
+
+ @Input()
+ popoverOnHover: boolean = false;
+
+ @Input()
+ popoverCloseOnClickOutside: boolean;
+
+ @Input()
+ popoverCloseOnMouseOutside: boolean;
+
+ @Input()
+ popoverDismissTimeout: number = 0;
+
+ @Output()
+ onShown = new EventEmitter<PopoverComponent>();
+
+ @Output()
+ onHidden = new EventEmitter<PopoverComponent>();
+
+ @HostListener("click")
+ showOrHideOnClick(): void {
+ if (this.popoverOnHover) return;
+ if (this.popoverDisabled) return;
+ this.toggle();
+ }
+
+ @HostListener("focusin")
+ @HostListener("mouseenter")
+ showOnHover(): void {
+ if (!this.popoverOnHover) return;
+ if (this.popoverDisabled) return;
+ this.show();
+ }
+
+ @HostListener("focusout")
+ @HostListener("mouseleave")
+ hideOnHover(): void {
+ if (this.popoverCloseOnMouseOutside) return;
+ if (!this.popoverOnHover) return;
+ if (this.popoverDisabled) return;
+ this.hide();
+ }
+
+ ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
+ if (changes["popoverDisabled"]) {
+ if (changes["popoverDisabled"].currentValue) {
+ this.hide();
+ }
+ }
+ }
+
+ toggle() {
+ if (!this.visible) {
+ this.show();
+ } else {
+ this.hide();
+ }
+ }
+
+ show() {
+ if (this.visible) return;
+
+ this.visible = true;
+ if (typeof this.content === "string") {
+ const factory = this.resolver.resolveComponentFactory(this.PopoverComponent);
+ if (!this.visible)
+ return;
+
+ this.popover = this.viewContainerRef.createComponent(factory);
+ const popover = this.popover.instance as PopoverContentComponent;
+ popover.popover = this;
+ popover.content = this.content as string;
+ if (this.popoverPlacement !== undefined)
+ popover.placement = this.popoverPlacement;
+ if (this.popoverAnimation !== undefined)
+ popover.animation = this.popoverAnimation;
+ if (this.popoverTitle !== undefined)
+ popover.title = this.popoverTitle;
+ if (this.popoverCloseOnClickOutside !== undefined)
+ popover.closeOnClickOutside = this.popoverCloseOnClickOutside;
+ if (this.popoverCloseOnMouseOutside !== undefined)
+ popover.closeOnMouseOutside = this.popoverCloseOnMouseOutside;
+
+ popover.onCloseFromOutside.subscribe(() => this.hide());
+ if (this.popoverDismissTimeout > 0)
+ setTimeout(() => this.hide(), this.popoverDismissTimeout);
+ } else {
+ const popover = this.content as PopoverContentComponent;
+ popover.popover = this;
+ if (this.popoverPlacement !== undefined)
+ popover.placement = this.popoverPlacement;
+ if (this.popoverAnimation !== undefined)
+ popover.animation = this.popoverAnimation;
+ if (this.popoverTitle !== undefined)
+ popover.title = this.popoverTitle;
+ if (this.popoverCloseOnClickOutside !== undefined)
+ popover.closeOnClickOutside = this.popoverCloseOnClickOutside;
+ if (this.popoverCloseOnMouseOutside !== undefined)
+ popover.closeOnMouseOutside = this.popoverCloseOnMouseOutside;
+
+ popover.onCloseFromOutside.subscribe(() => this.hide());
+ if (this.popoverDismissTimeout > 0)
+ setTimeout(() => this.hide(), this.popoverDismissTimeout);
+ popover.show();
+ }
+
+ this.onShown.emit(this);
+ }
+
+ hide() {
+ if (!this.visible) return;
+
+ this.visible = false;
+ if (this.popover)
+ this.popover.destroy();
+
+ if (this.content instanceof PopoverContentComponent)
+ (this.content as PopoverContentComponent).hideFromPopover();
+
+ this.onHidden.emit(this);
+ }
+
+ getElement() {
+ return this.viewContainerRef.element.nativeElement;
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/popover/popover.module.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover.module.ts
new file mode 100644
index 0000000000..d8cacc1696
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/popover/popover.module.ts
@@ -0,0 +1,45 @@
+/*-
+ * ============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=========================================================
+ */
+
+/**
+ * Created by rc2122 on 5/17/2017.
+ */
+import {NgModule} from "@angular/core";
+import { CommonModule } from '@angular/common';
+import {PopoverComponent} from "./popover.component";
+import {PopoverContentComponent} from "./popover-content.component";
+
+@NgModule({
+ declarations: [
+ PopoverComponent,
+ PopoverContentComponent
+ ],
+ imports: [
+ CommonModule
+ ],
+ exports: [
+ PopoverComponent,
+ PopoverContentComponent
+ ],
+ providers: []
+})
+export class PopoverModule {
+
+}
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/ui/tooltip/tooltip-content.component.html b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.html
new file mode 100644
index 0000000000..1fbf45e39f
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.html
@@ -0,0 +1,12 @@
+<div class="tooltip {{ placement }}"
+ [style.top]="top + 'px'"
+ [style.left]="left + 'px'"
+ [class.in]="isIn"
+ [class.fade]="isFade"
+ role="tooltip">
+ <div class="tooltip-arrow"></div>
+ <div class="tooltip-inner">
+ <ng-content></ng-content>
+ {{ content }}
+ </div>
+</div>
diff --git a/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.less b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.less
new file mode 100644
index 0000000000..1ff496f840
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.less
@@ -0,0 +1,11 @@
+.tooltip-inner {
+ word-wrap: break-word;
+ max-width: 300px;
+}
+
+.tooltip.bottom .tooltip-arrow {
+ border-bottom-color: #000 !important;
+}
+
+
+
diff --git a/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.ts b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.ts
new file mode 100644
index 0000000000..4dcb64c499
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.ts
@@ -0,0 +1,215 @@
+/*-
+ * ============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, AfterViewInit, Input, ElementRef, ChangeDetectorRef} from "@angular/core";
+
+@Component
+({
+ selector: "tooltip-content",
+ templateUrl: "./tooltip-content.component.html",
+ styleUrls: ["./tooltip-content.component.less"]
+})
+
+export class TooltipContentComponent implements AfterViewInit {
+
+ // -------------------------------------------------------------------------
+ // Inputs / Outputs
+ // -------------------------------------------------------------------------
+
+ @Input() hostElement: HTMLElement;
+ @Input() content: string;
+ @Input() placement: "top"|"bottom"|"left"|"right" = "bottom";
+ @Input() animation: boolean = true;
+
+ // -------------------------------------------------------------------------
+ // Properties
+ // -------------------------------------------------------------------------
+
+ top: number = -100000;
+ left: number = -100000;
+ isIn: boolean = false;
+ isFade: boolean = false;
+
+ // -------------------------------------------------------------------------
+ // Constructor
+ // -------------------------------------------------------------------------
+
+ constructor(private element: ElementRef,
+ private cdr: ChangeDetectorRef) {
+ }
+
+ // -------------------------------------------------------------------------
+ // Lifecycle callbacks
+ // -------------------------------------------------------------------------
+
+ ngAfterViewInit(): void {
+ this.show();
+ this.cdr.detectChanges();
+ }
+
+ // -------------------------------------------------------------------------
+ // Public Methods
+ // -------------------------------------------------------------------------
+
+ show(): void {
+ if(!this.hostElement) {
+ return;
+ }
+
+ const position = this.positionElement(this.hostElement, this.element.nativeElement.children[0], this.placement);
+ this.top = position.top;
+ this.left = position.left;
+ this.isIn = true;
+ if (this.animation) {
+ this.isFade = true;
+ }
+ }
+
+ hide(): void {
+ this.top = -100000;
+ this.left = -100000;
+ this.isIn = true;
+ if(this.animation) {
+ this.isFade = false;
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Private Methods
+ // -------------------------------------------------------------------------
+
+ private positionElement(hostElem: HTMLElement, targetElem: HTMLElement, positionStr: string, appendToBody: boolean = false): {top: number, left: number} {
+ let positionStrParts = positionStr.split("-");
+ let pos0 = positionStrParts[0];
+ let pos1 = positionStrParts[1] || "center";
+ let hostElemPosition = appendToBody ? this.offset(hostElem) : this.position(hostElem);
+ let targetElemWidth = targetElem.offsetWidth;
+ let targetElemHeight = targetElem.offsetHeight;
+ let shiftWidth: any = {
+ center(): number {
+ return hostElemPosition.left + hostElemPosition.width / 2 - targetElemWidth / 2;
+ },
+ left(): number {
+ return hostElemPosition.left;
+ },
+ right(): number {
+ return hostElemPosition.left + hostElemPosition.width;
+ }
+ };
+
+ let shiftHeight: any = {
+ center: function (): number {
+ return hostElemPosition.top + hostElemPosition.height / 2 - targetElemHeight / 2;
+ },
+ top: function (): number {
+ return hostElemPosition.top;
+ },
+ bottom: function (): number {
+ return hostElemPosition.top + hostElemPosition.height;
+ }
+ }
+
+ let targetElemPosition: {top: number, left: number};
+
+ switch (pos0) {
+ case "right":
+ targetElemPosition = {
+ top: shiftHeight[pos1](),
+ left: shiftWidth[pos0]()
+ };
+ break;
+
+ case "left":
+ targetElemPosition = {
+ top: shiftHeight[pos1](),
+ left: hostElemPosition.left - targetElemWidth
+ };
+ break;
+
+ case "bottom":
+ targetElemPosition = {
+ top: shiftHeight[pos0](),
+ left: shiftWidth[pos1]()
+ };
+ break;
+
+ default:
+ targetElemPosition = {
+ top: hostElemPosition.top - targetElemHeight,
+ left: shiftWidth[pos1]()
+ };
+ break;
+ }
+
+ return targetElemPosition;
+ }
+
+
+ private position(nativeElem: HTMLElement): {width: number, height: number, top: number, left: number} {
+ let offsetParentCBR = {top: 0, left: 0};
+ const elemBCR = this.offset(nativeElem);
+ const offsetParentElem = this.parentOffsetElem(nativeElem);
+ if(offsetParentElem !== window.document) {
+ offsetParentCBR = this.offset(offsetParentElem);
+ offsetParentCBR.top += offsetParentElem.clientTop - offsetParentElem.scrollTop;
+ offsetParentCBR.left += offsetParentElem.clientLeft - offsetParentElem.scrollTop;
+ }
+
+ const boundingClientRect = nativeElem.getBoundingClientRect();
+
+ return {
+ width: boundingClientRect.width || nativeElem.offsetWidth,
+ height: boundingClientRect.height || nativeElem.offsetHeight,
+ top: elemBCR.top - offsetParentCBR.top,
+ left: elemBCR.left - offsetParentCBR.left
+ };
+ }
+
+ private offset(nativeElem:any): {width: number, height: number, top: number, left: number} {
+ const boundingClientRect = nativeElem.getBoundingClientRect();
+ return {
+ width: boundingClientRect.width || nativeElem.offsetWidth,
+ height: boundingClientRect.height || nativeElem.offsetHeight,
+ top: boundingClientRect.top + (window.pageYOffset || window.document.documentElement.scrollTop),
+ left: boundingClientRect.left + (window.pageXOffset || window.document.documentElement.scrollLeft)
+ };
+ }
+
+ private getStyle(nativeElem: HTMLElement, cssProperty: string): string {
+ if(window.getComputedStyle) {
+ return (window.getComputedStyle(nativeElem) as any)[cssProperty];
+ }
+
+ return (nativeElem.style as any)[cssProperty];
+ }
+
+ private isStaticPositioned(nativeElem: HTMLElement): boolean {
+ return (this.getStyle(nativeElem, "position") || "static") === "static";
+ }
+
+ private parentOffsetElem(nativeElem: HTMLElement): any {
+ let offsetParent: any = nativeElem.offsetParent || window.document;
+ while (offsetParent && offsetParent !== window.document && this.isStaticPositioned(offsetParent)) {
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return offsetParent || window.document;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.component.ts b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.component.ts
new file mode 100644
index 0000000000..79d35c6e0e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.component.ts
@@ -0,0 +1,109 @@
+/*-
+ * ============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 {
+ Directive, ComponentRef, ViewContainerRef, ComponentFactoryResolver, Input, HostListener
+} from "@angular/core";
+import {TooltipContentComponent} from "./tooltip-content.component";
+
+@Directive ({
+ selector: "[tooltip]"
+})
+export class TooltipComponent {
+
+ // -------------------------------------------------------------------------
+ // Properties
+ // -------------------------------------------------------------------------
+
+ private tooltip: ComponentRef<TooltipContentComponent>;
+ private visible: boolean;
+ private delayInProgress: boolean = false;
+
+ // -------------------------------------------------------------------------
+ // Constructor
+ // -------------------------------------------------------------------------
+
+ constructor(private viewContainerRef: ViewContainerRef,
+ private resolver: ComponentFactoryResolver) {
+ }
+
+ // -------------------------------------------------------------------------
+ // Inputs / Outputs
+ // -------------------------------------------------------------------------
+
+ @Input("tooltip") content: string|TooltipContentComponent;
+ @Input() tooltipDisabled: boolean;
+ @Input() tooltipAnimation: boolean = true;
+ @Input() tooltipPlacement: "top"|"bottom"|"left"|"right" = "bottom";
+ @Input() tooltipDelay: number = 1500;
+
+ // -------------------------------------------------------------------------
+ // Public Methods
+ // -------------------------------------------------------------------------
+
+ @HostListener("mouseenter")
+ show(): void {
+ if(this.tooltipDisabled || this.visible || this.content === "") {
+ return;
+ }
+ if (this.tooltipDelay && !this.delayInProgress) {
+ this.delayInProgress = true;
+ setTimeout(() => { this.delayInProgress && this.show() }, this.tooltipDelay);
+ return;
+ }
+
+ this.visible = true;
+ if (typeof this.content === "string") {
+ const factory = this.resolver.resolveComponentFactory(TooltipContentComponent);
+ if (!this.visible) {
+ return;
+ }
+
+ this.tooltip = this.viewContainerRef.createComponent(factory);
+ this.tooltip.instance.hostElement = this.viewContainerRef.element.nativeElement;
+ this.tooltip.instance.content = this.content as string;
+ this.tooltip.instance.placement = this.tooltipPlacement;
+ this.tooltip.instance.animation = this.tooltipAnimation;
+ } else {
+ const tooltip = this.content as TooltipContentComponent;
+ tooltip.hostElement = this.viewContainerRef.element.nativeElement;
+ tooltip.placement = this.tooltipPlacement;
+ tooltip.animation = this.tooltipAnimation;
+ tooltip.show();
+ }
+ }
+
+ @HostListener("mouseleave")
+ hide(): void {
+ this.delayInProgress = false;
+ if (!this.visible) {
+ return;
+ }
+
+ this.visible = false;
+ if (this.tooltip) {
+ this.tooltip.destroy();
+ }
+ if (this.content instanceof TooltipContentComponent) {
+ (this.content as TooltipContentComponent).hide();
+ }
+ }
+}
+
diff --git a/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.module.ts b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.module.ts
new file mode 100644
index 0000000000..24478cd716
--- /dev/null
+++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.module.ts
@@ -0,0 +1,44 @@
+/*-
+ * ============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 {TooltipContentComponent} from "./tooltip-content.component";
+import {TooltipComponent} from "./tooltip.component";
+import {CommonModule} from "@angular/common";
+
+@NgModule({
+ declarations: [
+ TooltipComponent,
+ TooltipContentComponent,
+ ],
+ imports: [
+ ],
+ exports: [
+ TooltipComponent,
+ TooltipContentComponent,
+ ],
+ entryComponents: [
+ TooltipContentComponent
+ ],
+ providers: []
+})
+export class TooltipModule {
+
+}
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 {}