ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ababiic...@apache.org
Subject [32/50] [abbrv] ambari git commit: AMBARI-21476 Log Search UI: implement pagination for logs list. (ababiichuk)
Date Wed, 30 Aug 2017 12:41:42 GMT
AMBARI-21476 Log Search UI: implement pagination for logs list. (ababiichuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c9338e61
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c9338e61
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c9338e61

Branch: refs/heads/trunk
Commit: c9338e6186dcab80536e8edc48974329b9831100
Parents: 2d5b756
Author: ababiichuk <ababiichuk@hortonworks.com>
Authored: Fri Jul 14 15:21:38 2017 +0300
Committer: ababiichuk <ababiichuk@hortonworks.com>
Committed: Fri Jul 14 15:21:38 2017 +0300

----------------------------------------------------------------------
 .../src/app/app.module.ts                       |   8 +-
 .../queries/audit-logs-query-params.class.ts    |  18 +-
 .../src/app/components/app.component.html       |  13 +-
 .../src/app/components/app.component.less       |   4 +
 .../dropdown-button.component.html              |  12 +-
 .../dropdown-button.component.ts                |  18 +-
 .../filter-button.component.spec.ts             |   5 -
 .../filter-button/filter-button.component.ts    |  32 +-
 .../filter-dropdown.component.spec.ts           |   5 -
 .../filter-dropdown.component.ts                |  55 +-
 .../filter-text-field.component.html            |   4 +-
 .../filter-text-field.component.spec.ts         |   6 +-
 .../filter-text-field.component.ts              |  33 +-
 .../filters-panel/filters-panel.component.html  |  25 +-
 .../filters-panel/filters-panel.component.less  |  40 +-
 .../filters-panel/filters-panel.component.ts    |   3 +-
 .../logs-list/logs-list.component.html          |   6 +-
 .../logs-list/logs-list.component.less          |   3 +-
 .../logs-list/logs-list.component.spec.ts       |  14 +-
 .../components/logs-list/logs-list.component.ts |  27 +-
 .../main-container.component.html               |   1 +
 .../main-container.component.less               |  24 +
 .../main-container/main-container.component.ts  |   8 +-
 .../menu-button/menu-button.component.html      |   4 +-
 .../menu-button/menu-button.component.ts        |   7 +-
 .../pagination-controls.component.html          |  23 +
 .../pagination-controls.component.less          |  22 +
 .../pagination-controls.component.spec.ts       |  43 +
 .../pagination-controls.component.ts            |  73 ++
 .../pagination/pagination.component.html        |  24 +
 .../pagination/pagination.component.less        |  28 +
 .../pagination/pagination.component.spec.ts     |  69 ++
 .../pagination/pagination.component.ts          |  72 ++
 .../src/app/components/variables.less           |  10 +
 .../src/app/mock-data.ts                        | 906 +++++++++++++++++++
 .../src/app/services/filtering.service.ts       |  50 +-
 .../src/app/services/mock-api-data.service.ts   |  15 +-
 .../src/assets/i18n/en.json                     |   3 +
 .../src/assets/mock-data.ts                     | 906 -------------------
 .../ambari-logsearch-web-new/src/main.ts        |   4 +-
 .../ambari-logsearch-web-new/tsconfig.json      |   3 +
 41 files changed, 1515 insertions(+), 1111 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts
index 580fffa..503aa46 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts
@@ -27,7 +27,7 @@ import {TranslateHttpLoader} from '@ngx-translate/http-loader';
 import {StoreModule} from '@ngrx/store';
 import {MomentModule} from 'angular2-moment';
 import {MomentTimezoneModule} from 'angular-moment-timezone';
-import {environment} from '../environments/environment';
+import {environment} from '@envs/environment';
 import {mockApiDataService} from '@app/services/mock-api-data.service'
 import {HttpClientService} from '@app/services/http-client.service';
 import {ComponentActionsService} from '@app/services/component-actions.service';
@@ -60,6 +60,8 @@ import {FilterButtonComponent} from '@app/components/filter-button/filter-button
 import {AccordionPanelComponent} from '@app/components/accordion-panel/accordion-panel.component';
 import {LogsListComponent} from '@app/components/logs-list/logs-list.component';
 import {DropdownButtonComponent} from '@app/components/dropdown-button/dropdown-button.component';
+import {PaginationComponent} from '@app/components/pagination/pagination.component';
+import {PaginationControlsComponent} from '@app/components/pagination-controls/pagination-controls.component';
 
 export function HttpLoaderFactory(http: Http) {
   // adding 'static' parameter to step over mock data request
@@ -95,7 +97,9 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR
     FilterButtonComponent,
     AccordionPanelComponent,
     LogsListComponent,
-    DropdownButtonComponent
+    DropdownButtonComponent,
+    PaginationComponent,
+    PaginationControlsComponent
   ],
   imports: [
     BrowserModule,

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/classes/queries/audit-logs-query-params.class.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/classes/queries/audit-logs-query-params.class.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/classes/queries/audit-logs-query-params.class.ts
index 749ed21..75ad097 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/classes/queries/audit-logs-query-params.class.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/classes/queries/audit-logs-query-params.class.ts
@@ -18,10 +18,22 @@
 
 import {QueryParams} from '@app/classes/queries/query-params.class';
 
+export const defaultParams = {
+  page: '0',
+  pageSize: '10'
+};
+
 export class AuditLogsQueryParams extends QueryParams {
-  startIndex?: string = '0';
-  page?: string = '0';
-  pageSize?: string = '25';
+  constructor(options: AuditLogsQueryParams) {
+    let finalParams = Object.assign({}, defaultParams, options);
+    const page = parseInt(finalParams.page),
+      pageSize = parseInt(finalParams.pageSize);
+    finalParams.startIndex = isNaN(page) || isNaN(pageSize) ? '' : (page * pageSize).toString();
+    super(finalParams);
+  }
+  page: string;
+  pageSize: string;
+  startIndex: string;
   sortBy?: string;
   sortType?: string;
   start_time?: string;

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.html
index 5add5d5..a353f4d 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.html
@@ -24,9 +24,12 @@
   </nav>
 </header>
 
-<!-- hidden element for moving the main bar outside the fixed header -->
-<div class="navbar invisible">
-  <h1>&nbsp;</h1>
-</div>
 
-<main-container></main-container>
+<main-container>
+  <ng-template>
+    <!-- hidden element for moving the main bar outside the fixed header -->
+    <div class="navbar invisible">
+      <h1>&nbsp;</h1>
+    </div>
+  </ng-template>
+</main-container>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.less
index f948b12..d1aa7ff 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.less
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.less
@@ -18,6 +18,10 @@
 @import 'variables';
 
 :host {
+  .full-size;
+  display: flex;
+  flex-direction: column;
+  background-color: @main-background-color; // TODO implement actual color
   line-height: @default-line-height;
 
   .navbar {

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.html
index 8eb92f0..bd0d528 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.html
@@ -16,8 +16,10 @@
 -->
 
 <div class="filter-label" *ngIf="label">{{label | translate}}</div>
-<button class="btn btn-link dropdown-toggle" data-toggle="dropdown">
-  {{selectedLabel | translate}} <span class="caret"></span>
-</button>
-<ul data-component="dropdown-list" [ngClass]="{'dropdown-menu': true, 'dropdown-menu-right': isRightAlign}" [items]="options"
-    (selectedItemChange)="writeValue($event)"></ul>
+<div [ngClass]="{'dropup': isDropup}">
+  <button class="btn btn-link dropdown-toggle" data-toggle="dropdown">
+    {{selectedLabel | translate}} <span class="caret"></span>
+  </button>
+  <ul data-component="dropdown-list" [ngClass]="{'dropdown-menu': true, 'dropdown-menu-right': isRightAlign}"
+      [items]="options" (selectedItemChange)="updateValue($event)"></ul>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
index 821f137..3aecd9e 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
@@ -17,7 +17,6 @@
  */
 
 import {Component, OnInit, Input} from '@angular/core';
-import {FilteringService} from '@app/services/filtering.service';
 import {ComponentActionsService} from '@app/services/component-actions.service';
 import {UtilsService} from '@app/services/utils.service';
 
@@ -28,7 +27,7 @@ import {UtilsService} from '@app/services/utils.service';
 })
 export class DropdownButtonComponent implements OnInit {
 
-  constructor(protected filtering: FilteringService, protected actions: ComponentActionsService, protected utils: UtilsService) {
+  constructor(protected actions: ComponentActionsService, protected utils: UtilsService) {
   }
 
   ngOnInit() {
@@ -53,18 +52,25 @@ export class DropdownButtonComponent implements OnInit {
   @Input()
   isRightAlign?: boolean = false;
 
-  private selectedValue?: any;
+  @Input()
+  isDropup?: boolean = false;
+
+  protected selectedValue?: any;
 
   selectedLabel: string;
 
   get value(): any {
-    return this.selectedValue == null ? this.defaultValue : this.selectedValue;
+    return this.selectedValue;
+  }
+
+  set value(value: any) {
+    this.selectedValue = value;
   }
 
-  writeValue(options: any) {
+  updateValue(options: any) {
     const value = options && options.value;
     if (this.utils.valueHasChanged(this.value, value)) {
-      this.selectedValue = value;
+      this.value = value;
       this.selectedLabel = options.label;
       if (this.action) {
         this.actions[this.action](value);

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts
index 370b46e..c410ad8 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts
@@ -19,7 +19,6 @@
 import {NO_ERRORS_SCHEMA} from '@angular/core';
 import {async, ComponentFixture, TestBed} from '@angular/core/testing';
 import {Http} from '@angular/http';
-import {FormControl, FormGroup} from '@angular/forms';
 import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
 import {TranslateHttpLoader} from '@ngx-translate/http-loader';
 import {StoreModule} from '@ngrx/store';
@@ -70,10 +69,6 @@ describe('FilterButtonComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(FilterButtonComponent);
     component = fixture.componentInstance;
-    component.filterName = 'f';
-    component.form = new FormGroup({
-      f: new FormControl()
-    });
     fixture.detectChanges();
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts
index 27456e6..dc6bf82 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts
@@ -17,9 +17,8 @@
  */
 
 import {Component, Input, forwardRef} from '@angular/core';
-import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormGroup} from '@angular/forms';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
 import {ComponentActionsService} from '@app/services/component-actions.service';
-import {FilteringService} from '@app/services/filtering.service';
 import {UtilsService} from '@app/services/utils.service';
 import {MenuButtonComponent} from '@app/components/menu-button/menu-button.component';
 
@@ -37,41 +36,36 @@ import {MenuButtonComponent} from '@app/components/menu-button/menu-button.compo
 })
 export class FilterButtonComponent extends MenuButtonComponent implements ControlValueAccessor {
 
-  constructor(protected actions: ComponentActionsService, private filtering: FilteringService, private utils: UtilsService) {
+  constructor(protected actions: ComponentActionsService, private utils: UtilsService) {
     super(actions);
   }
 
   @Input()
-  filterName: string;
+  defaultValue?: string;
 
-  @Input()
-  form: FormGroup;
+  private selectedValue: any;
 
   private onChange: (fn: any) => void;
 
-  get filterInstance(): any {
-    return this.filtering.filters[this.filterName];
-  }
-
   get value(): any {
-    return this.filterInstance.selectedValue;
+    return this.selectedValue;
   }
 
   set value(newValue: any) {
-    if (this.utils.valueHasChanged(this.filterInstance.selectedValue, newValue)) {
-      this.filterInstance.selectedValue = newValue;
-      this.onChange(newValue);
-    }
+    this.selectedValue = newValue;
+    this.onChange(newValue);
   }
 
-  writeValue(options: any) {
+  updateValue(options: any) {
     const value = options && options.value;
-    if (this.utils.valueHasChanged(this.filterInstance.selectedValue, value)) {
-      this.filterInstance.selectedValue = value;
-      this.filterInstance.selectedLabel = options.label;
+    if (this.utils.valueHasChanged(this.selectedValue, value)) {
+      this.value = value;
     }
   }
 
+  writeValue() {
+  }
+
   registerOnChange(callback: any): void {
     this.onChange = callback;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
index e05ef48..323aa56 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
@@ -18,7 +18,6 @@
 import {NO_ERRORS_SCHEMA} from '@angular/core';
 import {async, ComponentFixture, TestBed} from '@angular/core/testing';
 import {Http} from '@angular/http';
-import {FormControl, FormGroup} from '@angular/forms';
 import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
 import {TranslateHttpLoader} from '@ngx-translate/http-loader';
 import {StoreModule} from '@ngrx/store';
@@ -83,10 +82,6 @@ describe('FilterDropdownComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(FilterDropdownComponent);
     component = fixture.componentInstance;
-    component.filterName = 'f';
-    component.form = new FormGroup({
-      f: new FormControl()
-    });
     fixture.detectChanges();
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts
index 9ebd821..8352ff1 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts
@@ -15,9 +15,8 @@
  * limitations under the License.
  */
 
-import {Component, Input, forwardRef} from '@angular/core';
-import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormGroup} from '@angular/forms';
-import {FilteringService} from '@app/services/filtering.service';
+import {Component, forwardRef} from '@angular/core';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
 import {ComponentActionsService} from '@app/services/component-actions.service';
 import {UtilsService} from '@app/services/utils.service';
 import {DropdownButtonComponent} from '@app/components/dropdown-button/dropdown-button.component';
@@ -36,58 +35,18 @@ import {DropdownButtonComponent} from '@app/components/dropdown-button/dropdown-
 })
 export class FilterDropdownComponent extends DropdownButtonComponent implements ControlValueAccessor {
 
-  constructor(protected filtering: FilteringService, protected actions: ComponentActionsService, protected utils: UtilsService) {
-    super(filtering, actions, utils);
+  constructor(protected actions: ComponentActionsService, protected utils: UtilsService) {
+    super(actions, utils);
   }
 
-  ngOnInit() {
-  }
-
-  @Input()
-  form: FormGroup;
-
-  @Input()
-  filterName: string;
-
   private onChange: (fn: any) => void;
 
-  get filterInstance(): any {
-    return this.filtering.filters[this.filterName];
-  }
-
-  get label(): string {
-    return this.filterInstance.label;
-  }
-
-  get defaultValue(): any {
-    return this.filterInstance.defaultValue;
-  }
-
-  get defaultLabel(): any {
-    return this.filterInstance.defaultLabel;
-  }
-
-  get value(): any {
-    return this.filterInstance.selectedValue == null ? this.defaultValue : this.filterInstance.selectedValue;
-  }
-
   set value(newValue: any) {
-    if (this.utils.valueHasChanged(this.filterInstance.selectedValue, newValue)) {
-      this.filterInstance.selectedValue = newValue;
-      this.onChange(newValue);
-    }
-  }
-
-  get selectedLabel(): string {
-    return this.filterInstance.selectedLabel == null ? this.defaultLabel : this.filterInstance.selectedLabel;
+    this.selectedValue = newValue;
+    this.onChange(newValue);
   }
 
-  writeValue(options: any): void {
-    const value = options && options.value;
-    if (this.utils.valueHasChanged(this.filterInstance.selectedValue, value)) {
-      this.filterInstance.selectedValue = value;
-      this.filterInstance.selectedLabel = options.label;
-    }
+  writeValue() {
   }
 
   registerOnChange(callback: any): void {

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html
index d135ba5..3f00e8b 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html
@@ -16,6 +16,6 @@
 -->
 
 <div class="input-group">
-  <span class="input-group-addon">{{filterInstance.label | translate}}</span>
-  <input type="text" class="form-control" [(ngModel)]="instantValue" (ngModelChange)="updateValue($event)">
+  <span class="input-group-addon">{{label | translate}}</span>
+  <input type="text" class="form-control" [(ngModel)]="instantValue" (ngModelChange)="updateInstantValue($event)">
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts
index a30e12a..71039ed 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts
@@ -18,7 +18,7 @@
 import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
 import {async, ComponentFixture, TestBed} from '@angular/core/testing';
 import {Http} from '@angular/http';
-import {FormsModule, FormControl, FormGroup} from '@angular/forms';
+import {FormsModule} from '@angular/forms';
 import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
 import {TranslateHttpLoader} from '@ngx-translate/http-loader';
 import {StoreModule} from '@ngrx/store';
@@ -73,10 +73,6 @@ describe('FilterTextFieldComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(FilterTextFieldComponent);
     component = fixture.componentInstance;
-    component.filterName = 'f';
-    component.form = new FormGroup({
-      f: new FormControl()
-    });
     fixture.detectChanges();
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts
index fe6ea34..2b6bfea 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts
@@ -19,7 +19,6 @@ import {Component, Input, forwardRef} from '@angular/core';
 import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormGroup} from '@angular/forms';
 import {Subject} from 'rxjs/Subject';
 import 'rxjs/add/operator/debounceTime';
-import {FilteringService} from '@app/services/filtering.service';
 import {UtilsService} from '@app/services/utils.service';
 
 @Component({
@@ -36,17 +35,16 @@ import {UtilsService} from '@app/services/utils.service';
 })
 export class FilterTextFieldComponent implements ControlValueAccessor {
 
-  constructor(private filtering: FilteringService, private utils: UtilsService) {
-    this.valueSubject.debounceTime(this.debounceInterval).subscribe(value => this.writeValue({
+  constructor(private utils: UtilsService) {
+    this.valueSubject.debounceTime(this.debounceInterval).subscribe(value => this.updateValue({
       value
     }));
   }
 
   @Input()
-  filterName: string;
+  label: string;
 
-  @Input()
-  form: FormGroup;
+  private selectedValue: string;
 
   private onChange: (fn: any) => void;
 
@@ -56,28 +54,25 @@ export class FilterTextFieldComponent implements ControlValueAccessor {
 
   private valueSubject = new Subject<string>();
 
-  get filterInstance(): any {
-    return this.filtering.filters[this.filterName];
-  }
-
   get value(): any {
-    return this.filterInstance.selectedValue;
+    return this.selectedValue;
   }
 
   set value(newValue: any) {
-    if (this.utils.valueHasChanged(this.filterInstance.selectedValue, newValue)) {
-      this.filterInstance.selectedValue = newValue;
-      this.onChange(newValue);
-    }
+    this.selectedValue = newValue;
+    this.onChange(newValue);
   }
 
-  writeValue(options: any) {
+  updateValue(options: any) {
     const value = options && options.value;
-    if (this.utils.valueHasChanged(this.filterInstance.selectedValue, value)) {
-      this.filterInstance.selectedValue = value;
+    if (this.utils.valueHasChanged(this.selectedValue, value)) {
+      this.value = value;
     }
   }
 
+  writeValue() {
+  }
+
   registerOnChange(callback: any): void {
     this.onChange = callback;
   }
@@ -85,7 +80,7 @@ export class FilterTextFieldComponent implements ControlValueAccessor {
   registerOnTouched() {
   }
 
-  updateValue(value: string): void {
+  updateInstantValue(value: string): void {
     this.valueSubject.next(value);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html
index 6547d88..d2de5e2 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html
@@ -15,14 +15,14 @@
   limitations under the License.
 -->
 
-<form [formGroup]="filtersForm">
+<form class="col-md-12" [formGroup]="filtersForm">
   <div class="form-inline filter-input-container col-md-8">
-    <filter-dropdown [(ngModel)]="filters.clusters.selectedValue" filterName="clusters" [form]="filtersForm"
-                     formControlName="clusters" [options]="filters.clusters.options"></filter-dropdown>
-    <filter-text-field [(ngModel)]="filters.text.selectedValue" filterName="text" formControlName="text"
-                       [form]="filtersForm"></filter-text-field>
-    <filter-dropdown [(ngModel)]="filters.timeRange.selectedValue" filterName="timeRange" [form]="filtersForm"
-                     formControlName="timeRange" [options]="filters.timeRange.options"></filter-dropdown>
+    <filter-dropdown [label]="filters.clusters.label" formControlName="clusters" [options]="filters.clusters.options"
+                     [defaultLabel]="filters.clusters.defaultLabel"></filter-dropdown>
+    <filter-text-field [label]="filters.text.label"
+                       formControlName="text"></filter-text-field>
+    <filter-dropdown formControlName="timeRange" [options]="filters.timeRange.options"
+                     [defaultLabel]="filters.timeRange.defaultLabel"></filter-dropdown>
     <dropdown-button [options]="timeZoneSelection.options" [defaultValue]="timeZoneSelection.defaultValue"
                      [defaultLabel]="timeZoneSelection.defaultLabel" action="setTimeZone"></dropdown-button>
     <!--button class="btn btn-success" type="button">
@@ -33,12 +33,11 @@
     <a href="#">
       <span class="fa fa-search-minus"></span> {{'filter.excluded' | translate}}
     </a>
-    <filter-button [(ngModel)]="filters.components.selectedValue" [form]="filtersForm" formControlName="components"
-                   [label]="filters.components.label" [iconClass]="filters.components.iconClass"
-                   [subItems]="filters.components.options" filterName="components"></filter-button>
-    <filter-button [(ngModel)]="filters.levels.selectedValue" [form]="filtersForm" formControlName="levels"
-                   [label]="filters.levels.label" [iconClass]="filters.levels.iconClass"
-                   [subItems]="filters.levels.options" filterName="levels"></filter-button>
+    <filter-button formControlName="components" [label]="filters.components.label"
+                   [iconClass]="filters.components.iconClass" [subItems]="filters.components.options"
+                   isRightAlign="true"></filter-button>
+    <filter-button formControlName="levels" [label]="filters.levels.label" [iconClass]="filters.levels.iconClass"
+                   [subItems]="filters.levels.options" isRightAlign="true"></filter-button>
     <menu-button label="filter.capture" iconClass="fa fa-caret-right"></menu-button>
   </div>
 </form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less
index aebd385..6b18e91 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less
@@ -18,28 +18,34 @@
 
 @import '../variables';
 
-.filter-input-container {
-  .flex-vertical-align;
-  justify-content: flex-start;
+:host {
+  display: block;
+  padding: @filters-panel-padding;
+  background-color: @filters-panel-background-color;
 
-  .btn-success {
-    border-top-left-radius: 0;
-    border-bottom-left-radius: 0;
-  }
-
-  filter-dropdown, dropdown-button {
-    border: @input-border;
+  .filter-input-container {
+    .flex-vertical-align;
+    justify-content: flex-start;
 
-    &:not(:last-child) {
-      border-right-width: 0;
+    .btn-success {
+      border-top-left-radius: 0;
+      border-bottom-left-radius: 0;
     }
 
-    &:first-child {
-      border-radius: @button-border-radius 0 0 @button-border-radius;
-    }
+    filter-dropdown, dropdown-button {
+      border: @input-border;
+
+      &:not(:last-child) {
+        border-right-width: 0;
+      }
+
+      &:first-child {
+        border-radius: @button-border-radius 0 0 @button-border-radius;
+      }
 
-    &:last-child {
-      border-radius: 0 @button-border-radius @button-border-radius 0;
+      &:last-child {
+        border-radius: 0 @button-border-radius @button-border-radius 0;
+      }
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts
index 9855bdd..b145a94 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts
@@ -17,6 +17,7 @@
  */
 
 import {Component} from '@angular/core';
+import {FormGroup} from '@angular/forms';
 import {FilteringService} from '@app/services/filtering.service';
 import {HttpClientService} from '@app/services/http-client.service';
 import {ClustersService} from '@app/services/storage/clusters.service';
@@ -62,7 +63,7 @@ export class FiltersPanelComponent {
     });
   }
 
-  get filtersForm() {
+  get filtersForm(): FormGroup {
     return this.filtering.filtersForm;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
index 5977ea2..4c84b9c 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
@@ -16,8 +16,8 @@
 -->
 
 <form *ngIf="(logs | async).length" [formGroup]="filtersForm">
-  <filter-dropdown [(ngModel)]="filters.sorting.selectedValue" filterName="sorting" [form]="filtersForm"
-                   formControlName="sorting" [options]="filters.sorting.options" isRightAlign="true"></filter-dropdown>
+  <filter-dropdown [label]="filters.sorting.label" formControlName="sorting" [options]="filters.sorting.options"
+                   [defaultLabel]="filters.sorting.defaultLabel" isRightAlign="true"></filter-dropdown>
 </form>
 <div class="col-md-12 text-center" *ngIf="(logs | async).length">
   <div class="logs-header">
@@ -43,3 +43,5 @@
     </div>
   </ng-template>
 </accordion-panel>
+<pagination class="col-md-12" *ngIf="(logs | async).length" [totalCount]="totalCount" [filtersForm]="filtersForm"
+            [filterInstance]="filters.pageSize" [currentCount]="(logs | async).length"></pagination>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less
index 8ebe870..76c16a5 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less
@@ -21,7 +21,6 @@
   display: block;
   overflow: hidden;
   padding-top: @block-margin-top;
-  background-color: @main-background-color; // TODO implement actual color
 
   .logs-header {
     // TODO get rid of magic numbers, base on actual design
@@ -32,7 +31,7 @@
     text-transform: uppercase;
   }
 
-  filter-dropdown {
+  /deep/ filter-dropdown {
     justify-content: flex-end;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
index 2c4f372..96adc8f 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
@@ -17,6 +17,9 @@
 
 import {NO_ERRORS_SCHEMA} from '@angular/core';
 import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+import {Http} from '@angular/http';
+import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
+import {TranslateHttpLoader} from '@ngx-translate/http-loader';
 import {StoreModule} from '@ngrx/store';
 import {MomentModule} from 'angular2-moment';
 import {MomentTimezoneModule} from 'angular-moment-timezone';
@@ -31,6 +34,10 @@ import {UtilsService} from '@app/services/utils.service';
 
 import {LogsListComponent} from './logs-list.component';
 
+export function HttpLoaderFactory(http: Http) {
+  return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
+}
+
 describe('LogsListComponent', () => {
   let component: LogsListComponent;
   let fixture: ComponentFixture<LogsListComponent>;
@@ -55,7 +62,12 @@ describe('LogsListComponent', () => {
           components
         }),
         MomentModule,
-        MomentTimezoneModule
+        MomentTimezoneModule,
+        TranslateModule.forRoot({
+          provide: TranslateLoader,
+          useFactory: HttpLoaderFactory,
+          deps: [Http]
+        })
       ],
       providers: [
         {

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts
index a070814..7427fc1 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts
@@ -16,6 +16,7 @@
  */
 
 import {Component, OnInit, Input} from '@angular/core';
+import {FormGroup} from '@angular/forms';
 import 'rxjs/add/operator/map';
 import {HttpClientService} from '@app/services/http-client.service';
 import {ServiceLogsService} from '@app/services/storage/service-logs.service';
@@ -41,6 +42,8 @@ export class LogsListComponent implements OnInit {
   @Input()
   private logsArrayId: string;
 
+  totalCount: number = 0;
+
   timeFormat: string = 'DD/MM/YYYY HH:mm:ss';
 
   private readonly usedFilters = {
@@ -49,7 +52,9 @@ export class LogsListComponent implements OnInit {
     timeRange: ['end_time', 'start_time'],
     components: ['component_name'],
     levels: ['level'],
-    sorting: ['sortType', 'sortBy']
+    sorting: ['sortType', 'sortBy'],
+    pageSize: ['pageSize'],
+    page: ['page']
   };
 
   logs = this.serviceLogsStorage.getAll().map(logs => logs.map(log => {
@@ -66,22 +71,26 @@ export class LogsListComponent implements OnInit {
     return this.filtering.timeZone;
   }
 
-  get filters() {
+  get filters(): any {
     return this.filtering.filters;
   }
   
-  get filtersForm() {
+  get filtersForm(): FormGroup {
     return this.filtering.filtersForm;
   }
 
   private loadLogs(): void {
     this.httpClient.get(this.logsArrayId, this.getParams()).subscribe(response => {
-      const jsonResponse = response.json(),
-        logs = jsonResponse && jsonResponse.logList;
+      const jsonResponse = response.json();
       this.serviceLogsStorage.clear();
-      if (logs) {
-        const logs = response.json().logList;
-        this.serviceLogsStorage.addInstances(logs);
+      if (jsonResponse) {
+        const logs = jsonResponse.logList,
+          count = jsonResponse.totalCount || 0;
+        if (logs) {
+          const logs = response.json().logList;
+          this.serviceLogsStorage.addInstances(logs);
+        }
+        this.totalCount = count;
       }
     });
   }
@@ -103,7 +112,7 @@ export class LogsListComponent implements OnInit {
         } else {
           value = inputValue;
         }
-        if (value) {
+        if (value != null && value !== '') {
           params[paramName] = value;
         }
       });

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html
index 97ed1ce..42a8fbf 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html
@@ -15,6 +15,7 @@
   limitations under the License.
 -->
 
+<ng-template [ngTemplateOutlet]="template"></ng-template>
 <div *ngIf="isInitialLoading" class="text-center">
   <span class="fa fa-spinner fa-spin"></span>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.less
new file mode 100644
index 0000000..9736628
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.less
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+@import '../variables';
+
+:host {
+  .full-size;
+  overflow-x: hidden;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.ts
index b279cf5..b0c3943 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.ts
@@ -16,12 +16,13 @@
  * limitations under the License.
  */
 
-import {Component} from '@angular/core';
+import {Component, ContentChild, TemplateRef} from '@angular/core';
 import {AppStateService} from '@app/services/storage/app-state.service';
 
 @Component({
   selector: 'main-container',
-  templateUrl: './main-container.component.html'
+  templateUrl: './main-container.component.html',
+  styleUrls: ['./main-container.component.less']
 })
 export class MainContainerComponent {
 
@@ -30,6 +31,9 @@ export class MainContainerComponent {
     this.appState.getParameter('isInitialLoading').subscribe(value => this.isInitialLoading = value);
   }
 
+  @ContentChild(TemplateRef)
+  template;
+
   isAuthorized: boolean = false;
 
   isInitialLoading: boolean = false;

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
index 031dec1..f18285f 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
@@ -22,6 +22,6 @@
   <br>
   <a *ngIf="label" (mousedown)="onMouseDown($event)" [ngClass]="labelClass" (mouseup)="onMouseUp($event)"
      (click)="$event.stopPropagation()">{{label | translate}}</a>
-  <ul data-component="dropdown-list" class="dropdown-menu" *ngIf="hasSubItems" [items]="subItems"
-      (selectedItemChange)="writeValue($event)"></ul>
+  <ul data-component="dropdown-list" *ngIf="hasSubItems" [items]="subItems" (selectedItemChange)="updateValue($event)"
+      [ngClass]="{'dropdown-menu': true, 'dropdown-menu-right': isRightAlign}"></ul>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
index e245fb3..d1baedc 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
@@ -49,7 +49,10 @@ export class MenuButtonComponent {
   subItems?: any[];
 
   @Input()
-  hideCaret?: boolean;
+  hideCaret?: boolean = false;
+
+  @Input()
+  isRightAlign?: boolean = false;
 
   get hasSubItems(): boolean {
     return Boolean(this.subItems && this.subItems.length);
@@ -81,7 +84,7 @@ export class MenuButtonComponent {
     }
   }
   
-  writeValue(options: any) {
+  updateValue(options: any) {
     // TODO implement value change behaviour
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.html
new file mode 100644
index 0000000..c227a2b
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.html
@@ -0,0 +1,23 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<button class="btn btn-link" [disabled]="currentPage === 0" (click)="updateValue(true)">
+  <span class="pagination-control fa fa-chevron-left"></span>
+</button>
+<button class="btn btn-link" [disabled]="currentPage === pagesCount - 1" (click)="updateValue()">
+  <span class="pagination-control fa fa-chevron-right"></span>
+</button>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.less
new file mode 100644
index 0000000..c21e83e
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.less
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+@import '../variables';
+
+.pagination-control {
+  .clickable-item;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.spec.ts
new file mode 100644
index 0000000..489f79c
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.spec.ts
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {PaginationControlsComponent} from './pagination-controls.component';
+
+describe('PaginationControlsComponent', () => {
+  let component: PaginationControlsComponent;
+  let fixture: ComponentFixture<PaginationControlsComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [PaginationControlsComponent]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PaginationControlsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create component', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.ts
new file mode 100644
index 0000000..c71844c
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination-controls/pagination-controls.component.ts
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import {Component, forwardRef, Input, Output, EventEmitter} from '@angular/core';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+
+@Component({
+  selector: 'pagination-controls',
+  templateUrl: './pagination-controls.component.html',
+  styleUrls: ['./pagination-controls.component.less'],
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => PaginationControlsComponent),
+      multi: true
+    }
+  ]
+})
+export class PaginationControlsComponent implements ControlValueAccessor {
+
+  private onChange: (fn: any) => void;
+
+  currentPage: number = 0;
+
+  @Input()
+  totalCount: number;
+
+  @Input()
+  pagesCount: number;
+
+  @Output()
+  currentPageChange: EventEmitter<number> = new EventEmitter();
+
+  get value(): number {
+    return this.currentPage;
+  }
+
+  set value(newValue: number) {
+    this.currentPage = newValue;
+    this.currentPageChange.emit(newValue);
+    this.onChange(newValue);
+  }
+
+  updateValue(isDecrement?: boolean) {
+    isDecrement? this.value-- : this.value++;
+  }
+
+  writeValue() {
+  }
+
+  registerOnChange(callback: any): void {
+    this.onChange = callback;
+  }
+
+  registerOnTouched() {
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.html
new file mode 100644
index 0000000..67fe591
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.html
@@ -0,0 +1,24 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<form class="pagination-form col-md-12" [formGroup]="filtersForm">
+  <filter-dropdown [label]="filterInstance.label" formControlName="pageSize" [options]="filterInstance.options"
+                   [defaultLabel]="filterInstance.defaultLabel" isRightAlign="true" isDropup="true"></filter-dropdown>
+  <span>{{'pagination.numbers' | translate: numbersTranslateParams}}</span>
+  <pagination-controls formControlName="page" [totalCount]="totalCount" [pagesCount]="pagesCount"
+                       (currentPageChange)="setCurrentPage($event)"></pagination-controls>
+</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.less
new file mode 100644
index 0000000..df8ad2d
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.less
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+@import '../variables';
+
+:host {
+  display: flex;
+
+  .pagination-form {
+    .flex-vertical-align;
+    justify-content: flex-end;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.spec.ts
new file mode 100644
index 0000000..7a15bbc
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.spec.ts
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+import {NO_ERRORS_SCHEMA} from '@angular/core';
+import {Http} from '@angular/http';
+import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
+import {TranslateHttpLoader} from '@ngx-translate/http-loader';
+
+import {PaginationComponent} from './pagination.component';
+
+export function HttpLoaderFactory(http: Http) {
+  return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
+}
+
+describe('PaginationComponent', () => {
+  let component: PaginationComponent;
+  let fixture: ComponentFixture<PaginationComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      imports: [
+        TranslateModule.forRoot({
+          provide: TranslateLoader,
+          useFactory: HttpLoaderFactory,
+          deps: [Http]
+        })
+      ],
+      declarations: [PaginationComponent],
+      schemas: [NO_ERRORS_SCHEMA]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PaginationComponent);
+    component = fixture.componentInstance;
+    component.filterInstance = {};
+    component.filtersForm = {
+      controls: {
+        pageSize: {
+          valueChanges: {
+            subscribe: () => {}
+          }
+        }
+      }
+    };
+    fixture.detectChanges();
+  });
+
+  it('should create component', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.ts
new file mode 100644
index 0000000..d38d0d8
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.ts
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import {Component, OnInit, Input} from '@angular/core';
+import {FormGroup} from '@angular/forms';
+
+@Component({
+  selector: 'pagination',
+  templateUrl: './pagination.component.html',
+  styleUrls: ['./pagination.component.less']
+})
+export class PaginationComponent implements OnInit {
+
+  ngOnInit() {
+    this.setPageSizeFromString(this.filterInstance.defaultValue);
+    this.filtersForm.controls.pageSize.valueChanges.subscribe(value => this.setPageSizeFromString(value));
+  }
+
+  @Input()
+  filtersForm: FormGroup;
+
+  @Input()
+  filterInstance: any;
+
+  @Input()
+  currentCount?: number;
+
+  @Input()
+  totalCount: number;
+
+  private pageSize: number = 0;
+
+  setPageSizeFromString(value: string) {
+    this.pageSize = parseInt(value);
+  }
+
+  private currentPage: number = 0;
+
+  get numbersTranslateParams(): any {
+    const pageSize = this.pageSize,
+      startIndex = (this.currentPage * pageSize) + 1;
+    return {
+      startIndex,
+      endIndex: startIndex + Math.min(pageSize, this.currentCount) - 1,
+      totalCount: this.totalCount
+    }
+  }
+
+  get pagesCount(): number {
+    return Math.ceil(this.totalCount / this.pageSize);
+  }
+
+  setCurrentPage(pageNumber: number) {
+    this.currentPage = pageNumber;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9338e61/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less
index c5f034c..7715876 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less
@@ -29,6 +29,8 @@
 @grey-color: #666;
 @default-line-height: 1.42857143;
 @main-background-color: #ECECEC;
+@filters-panel-background-color: #FFF;
+@filters-panel-padding: 10px 0;
 @list-header-background-color: #F2F2F2;
 
 @fatal-color: #830A0A;
@@ -86,3 +88,11 @@
     color: @link-hover-color;
   }
 }
+
+.full-size {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}


Mime
View raw message