AMBARI-21382 Log Search UI: implement timezone customization. (ababiichuk)

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

Branch: refs/heads/branch-feature-logsearch-ui
Commit: b7edc6cf8db108aa5b703817870a8d077c2e7180
Parents: ed66094
Author: ababiichuk <ababiic...@hortonworks.com>
Authored: Fri Jun 30 16:29:49 2017 +0300
Committer: ababiichuk <ababiic...@hortonworks.com>
Committed: Fri Jun 30 16:29:49 2017 +0300

----------------------------------------------------------------------
 .../ambari-logsearch-web-new/package.json       |  2 +
 .../src/app/app.module.ts                       | 14 ++-
 .../dropdown-list/dropdown-list.component.less  |  2 +-
 .../filter-button.component.spec.ts             | 75 ++++++++++++++++
 .../filter-button/filter-button.component.ts    | 91 ++++++++++++++++++++
 .../filter-dropdown.component.html              |  2 +-
 .../filter-dropdown.component.spec.ts           | 84 +++++++++---------
 .../filter-dropdown.component.ts                | 65 +++++++++++---
 .../filter-text-field.component.html            |  3 +-
 .../filter-text-field.component.spec.ts         | 25 +++++-
 .../filter-text-field.component.ts              | 61 +++++++++++--
 .../filters-panel/filters-panel.component.html  | 51 ++++++-----
 .../filters-panel.component.spec.ts             | 26 ++++--
 .../filters-panel/filters-panel.component.ts    | 16 +++-
 .../logs-list/logs-list.component.html          |  2 +-
 .../logs-list/logs-list.component.spec.ts       | 11 ++-
 .../components/logs-list/logs-list.component.ts |  9 +-
 .../menu-button/menu-button.component.html      |  4 +-
 .../menu-button/menu-button.component.spec.ts   |  8 +-
 .../menu-button/menu-button.component.ts        | 23 ++---
 .../src/app/models/app-settings.model.ts        | 27 ++++++
 .../src/app/models/store.model.ts               | 53 ++++++++++--
 .../src/app/services/filtering.service.spec.ts  | 12 ++-
 .../src/app/services/filtering.service.ts       | 51 +++++++----
 .../services/storage/app-settings.service.ts    | 33 +++++++
 .../app/services/storage/audit-logs.service.ts  |  7 +-
 .../app/services/storage/bar-graphs.service.ts  |  7 +-
 .../src/app/services/storage/filters.service.ts |  6 +-
 .../src/app/services/storage/graphs.service.ts  |  6 +-
 .../src/app/services/storage/nodes.service.ts   |  6 +-
 .../services/storage/service-logs.service.ts    |  6 +-
 .../services/storage/user-configs.service.ts    |  6 +-
 .../src/assets/mock-data.ts                     | 30 ++++---
 .../ambari-logsearch-web-new/yarn.lock          | 28 +++++-
 34 files changed, 658 insertions(+), 194 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/package.json
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/package.json 
b/ambari-logsearch/ambari-logsearch-web-new/package.json
index da44d30..847787b 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/package.json
+++ b/ambari-logsearch/ambari-logsearch-web-new/package.json
@@ -23,6 +23,8 @@
     "@ngrx/store": "^2.2.2",
     "@ngx-translate/core": "^6.0.1",
     "@ngx-translate/http-loader": "^0.0.3",
+    "angular-moment-timezone": "^0.2.1",
+    "angular2-moment": "^1.4.0",
     "bootstrap": "^3.3.7",
     "core-js": "^2.4.1",
     "font-awesome": "^4.7.0",

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 a095a97..1e0ebb0 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
@@ -18,19 +18,22 @@
 
 import {BrowserModule} from '@angular/platform-browser';
 import {NgModule, CUSTOM_ELEMENTS_SCHEMA, Injector} from '@angular/core';
-import {FormsModule} from '@angular/forms';
+import {FormsModule, ReactiveFormsModule} from '@angular/forms';
 import {HttpModule, Http, XHRBackend, BrowserXhr, ResponseOptions, 
XSRFStrategy} from '@angular/http';
 import {InMemoryBackendService} from 'angular-in-memory-web-api';
 import {AlertModule} from 'ngx-bootstrap';
 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';
 import {environment} from '../environments/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';
 import {FilteringService} from '@app/services/filtering.service';
 
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 import {AuditLogsService, auditLogs} from 
'@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from 
'@app/services/storage/service-logs.service';
 import {BarGraphsService, barGraphs} from 
'@app/services/storage/bar-graphs.service';
@@ -48,6 +51,7 @@ import {FiltersPanelComponent} from 
'@app/components/filters-panel/filters-panel
 import {FilterDropdownComponent} from 
'@app/components/filter-dropdown/filter-dropdown.component';
 import {DropdownListComponent} from 
'@app/components/dropdown-list/dropdown-list.component';
 import {FilterTextFieldComponent} from 
'@app/components/filter-text-field/filter-text-field.component';
+import {FilterButtonComponent} from 
'@app/components/filter-button/filter-button.component';
 import {AccordionPanelComponent} from 
'@app/components/accordion-panel/accordion-panel.component';
 import {LogsListComponent} from 
'@app/components/logs-list/logs-list.component';
 
@@ -82,12 +86,14 @@ export function getXHRBackend(injector: Injector, browser: 
BrowserXhr, xsrf: XSR
     DropdownListComponent,
     FilterDropdownComponent,
     FilterTextFieldComponent,
+    FilterButtonComponent,
     AccordionPanelComponent,
     LogsListComponent
   ],
   imports: [
     BrowserModule,
     FormsModule,
+    ReactiveFormsModule,
     HttpModule,
     AlertModule.forRoot(),
     TranslateModule.forRoot({
@@ -98,6 +104,7 @@ export function getXHRBackend(injector: Injector, browser: 
BrowserXhr, xsrf: XSR
       }
     }),
     StoreModule.provideStore({
+      appSettings,
       auditLogs,
       serviceLogs,
       barGraphs,
@@ -105,12 +112,15 @@ export function getXHRBackend(injector: Injector, 
browser: BrowserXhr, xsrf: XSR
       nodes,
       userConfigs,
       filters
-    })
+    }),
+    MomentModule,
+    MomentTimezoneModule
   ],
   providers: [
     HttpClientService,
     ComponentActionsService,
     FilteringService,
+    AppSettingsService,
     AuditLogsService,
     ServiceLogsService,
     BarGraphsService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
index d0f079a..0853883 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
@@ -19,4 +19,4 @@
 :host {
   max-height: 500px; // TODO get rid of magic number, base on actual design
   overflow-y: auto;
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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
new file mode 100644
index 0000000..8828390
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts
@@ -0,0 +1,75 @@
+/**
+ * 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 {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';
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
+import {ComponentActionsService} from 
'@app/services/component-actions.service';
+import {FilteringService} from '@app/services/filtering.service';
+
+import {FilterButtonComponent} from './filter-button.component';
+
+export function HttpLoaderFactory(http: Http) {
+  return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
+}
+
+describe('FilterButtonComponent', () => {
+  let component: FilterButtonComponent;
+  let fixture: ComponentFixture<FilterButtonComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [FilterButtonComponent],
+      imports: [
+        StoreModule.provideStore({
+          appSettings
+        }),
+        TranslateModule.forRoot({
+          provide: TranslateLoader,
+          useFactory: HttpLoaderFactory,
+          deps: [Http]
+        })],
+      providers: [
+        AppSettingsService,
+        ComponentActionsService,
+        FilteringService
+      ],
+      schemas: [NO_ERRORS_SCHEMA]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(FilterButtonComponent);
+    component = fixture.componentInstance;
+    component.filterName = 'f';
+    component.form = new FormGroup({
+      f: new FormControl()
+    });
+    fixture.detectChanges();
+  });
+
+  it('should create component', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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
new file mode 100644
index 0000000..3da53ca
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts
@@ -0,0 +1,91 @@
+/**
+ * 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, Input, forwardRef} from '@angular/core';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormGroup} from 
'@angular/forms';
+import {ComponentActionsService} from 
'@app/services/component-actions.service';
+import {FilteringService} from '@app/services/filtering.service';
+import {MenuButtonComponent, menuButtonComponentOptions} from 
'@app/components/menu-button/menu-button.component';
+
+@Component(Object.assign({
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => FilterButtonComponent),
+      multi: true
+    }
+  ]
+}, menuButtonComponentOptions, {
+  selector: 'filter-button',
+}))
+export class FilterButtonComponent extends MenuButtonComponent implements 
ControlValueAccessor {
+
+  constructor(protected actions: ComponentActionsService, private filtering: 
FilteringService) {
+    super(actions);
+  }
+
+  ngAfterViewInit() {
+    const callback = this.customOnChange ?
+      (value => this.customOnChange(value)) : (() => 
this.filtering.filteringSubject.next(null));
+    this.form.controls[this.filterName].valueChanges.subscribe(callback);
+  }
+
+  @Input()
+  filterName: string;
+
+  @Input()
+  customOnChange: (value: any) => void;
+
+  @Input()
+  form: FormGroup;
+
+  private onChange: (fn: any) => void;
+
+  readonly isFilter = true;
+
+  get filterInstance(): any {
+    return this.filtering.filters[this.filterName];
+  }
+
+  get value(): any {
+    return this.filterInstance.selectedValue;
+  }
+
+  set value(newValue: any) {
+    if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, 
newValue)) {
+      this.filterInstance.selectedValue = newValue;
+      this.onChange(newValue);
+    }
+  }
+
+  writeValue(options: any) {
+    const value = options && options.value;
+    if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, 
value)) {
+      this.filterInstance.selectedValue = value;
+      this.filterInstance.selectedLabel = options.label;
+    }
+  }
+
+  registerOnChange(callback: any): void {
+    this.onChange = callback;
+  }
+
+  registerOnTouched() {
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.html
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.html
index 1ac663e..bb7a206 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.html
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.html
@@ -20,4 +20,4 @@
   {{filterInstance.selectedLabel | translate}} <span class="caret"></span>
 </button>
 <ul class="dropdown-menu" [items]="filterInstance.options" [isFilter]="true"
-    (selectedItemChange)="setSelectedValue($event)"></ul>
+    (selectedItemChange)="writeValue($event)"></ul>

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 e0414f3..9f4522b 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,8 +18,11 @@
 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';
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 import {FilteringService} from '@app/services/filtering.service';
 
 import {FilterDropdownComponent} from './filter-dropdown.component';
@@ -31,16 +34,43 @@ export function HttpLoaderFactory(http: Http) {
 describe('FilterDropdownComponent', () => {
   let component: FilterDropdownComponent;
   let fixture: ComponentFixture<FilterDropdownComponent>;
+  const filtering = {
+    filters: {
+      f: {
+        options: [
+          {
+            value: 'v0',
+            label: 'l0'
+          },
+          {
+            value: 'v1',
+            label: 'l1'
+          }
+        ]
+      }
+    }
+  };
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
       declarations: [FilterDropdownComponent],
-      imports: [TranslateModule.forRoot({
-        provide: TranslateLoader,
-        useFactory: HttpLoaderFactory,
-        deps: [Http]
-      })],
-      providers: [FilteringService],
+      imports: [
+        StoreModule.provideStore({
+          appSettings
+        }),
+        TranslateModule.forRoot({
+          provide: TranslateLoader,
+          useFactory: HttpLoaderFactory,
+          deps: [Http]
+        })
+      ],
+      providers: [
+        AppSettingsService,
+        {
+          provide: FilteringService,
+          useValue: filtering
+        }
+      ],
       schemas: [NO_ERRORS_SCHEMA]
     })
     .compileComponents();
@@ -49,18 +79,10 @@ describe('FilterDropdownComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(FilterDropdownComponent);
     component = fixture.componentInstance;
-    component.filterInstance = {
-      options: [
-        {
-          value: 'v0',
-          label: 'l0'
-        },
-        {
-          value: 'v1',
-          label: 'l1'
-        }
-      ]
-    };
+    component.filterName = 'f';
+    component.form = new FormGroup({
+      f: new FormControl()
+    });
     fixture.detectChanges();
   });
 
@@ -68,30 +90,4 @@ describe('FilterDropdownComponent', () => {
     expect(component).toBeTruthy();
   });
 
-  describe('should take initial filter values from 1st item', () => {
-    it('selectedValue', () => {
-      expect(component.filterInstance.selectedValue).toEqual('v0');
-    });
-
-    it('selectedLabel', () => {
-      expect(component.filterInstance.selectedLabel).toEqual('l0');
-    });
-  });
-
-  describe('#setSelectedValue()', () => {
-    beforeEach(() => {
-      component.setSelectedValue({
-        value: 'v2',
-        label: 'l2'
-      });
-    });
-
-    it('selectedValue', () => {
-      expect(component.filterInstance.selectedValue).toEqual('v2');
-    });
-
-    it('selectedLabel', () => {
-      expect(component.filterInstance.selectedLabel).toEqual('l2');
-    });
-  });
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 faaafcb..84210dc 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,36 +15,75 @@
  * limitations under the License.
  */
 
-import {Component, OnInit, Input} from '@angular/core';
+import {Component, AfterViewInit, Input, forwardRef} from '@angular/core';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormGroup} from 
'@angular/forms';
 import {FilteringService} from '@app/services/filtering.service';
 
 @Component({
   selector: 'filter-dropdown',
   templateUrl: './filter-dropdown.component.html',
-  styleUrls: ['./filter-dropdown.component.less']
+  styleUrls: ['./filter-dropdown.component.less'],
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => FilterDropdownComponent),
+      multi: true
+    }
+  ]
 })
-export class FilterDropdownComponent implements OnInit {
+export class FilterDropdownComponent implements AfterViewInit, 
ControlValueAccessor {
 
   constructor(private filtering: FilteringService) {
   }
 
-  ngOnInit() {
-    this.filterInstance.selectedValue = this.filterInstance.options[0].value;
-    this.filterInstance.selectedLabel = this.filterInstance.options[0].label;
+  ngAfterViewInit() {
+    const callback = this.customOnChange ?
+      (value => this.customOnChange(value)) : (() => 
this.filtering.filteringSubject.next(null));
+    this.form.controls[this.filterName].valueChanges.subscribe(callback);
   }
 
   @Input()
-  filterInstance: any;
+  options: any[];
 
   @Input()
-  options: any[];
+  customOnChange: (value: any) => void;
+
+  @Input()
+  form: FormGroup;
+
+  @Input()
+  filterName: string;
+
+  private onChange: (fn: any) => void;
+
+  get filterInstance(): any {
+    return this.filtering.filters[this.filterName];
+  }
 
-  setSelectedValue(options: any): void {
-    if (this.filterInstance.selectedValue !== options.value) {
-      this.filterInstance.selectedValue = options.value;
+  get value(): any {
+    return this.filterInstance.selectedValue;
+  }
+
+  set value(newValue: any) {
+    if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, 
newValue)) {
+      this.filterInstance.selectedValue = newValue;
+      this.onChange(newValue);
+    }
+  }
+
+  writeValue(options: any) {
+    const value = options && options.value;
+    if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, 
value)) {
+      this.filterInstance.selectedValue = value;
       this.filterInstance.selectedLabel = options.label;
-      this.filtering.filteringSubject.next(null);
     }
-  };
+  }
+
+  registerOnChange(callback: any): void {
+    this.onChange = callback;
+  }
+
+  registerOnTouched() {
+  }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 ed3c4ba..8fb7659 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
@@ -17,5 +17,6 @@
 
 <div class="input-group">
   <span class="input-group-addon">{{filterInstance.label | translate}}</span>
-  <input type="text" class="form-control" 
[(ngModel)]="filterInstance.selectedValue" (change)="onValueChange()"> <!-- 
TODO use ngModelChange with debounce -->
+  <input type="text" class="form-control" 
[(ngModel)]="filterInstance.selectedValue"
+         (ngModelChange)="writeValue($event)">
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 e4f026c..740593f 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,9 +18,11 @@
 import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
 import {async, ComponentFixture, TestBed} from '@angular/core/testing';
 import {Http} from '@angular/http';
-import {FormsModule} from '@angular/forms';
+import {FormsModule, FormControl, FormGroup} from '@angular/forms';
 import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
 import {TranslateHttpLoader} from '@ngx-translate/http-loader';
+import {StoreModule} from '@ngrx/store';
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 import {FilteringService} from '@app/services/filtering.service';
 
 import {FilterTextFieldComponent} from './filter-text-field.component';
@@ -32,6 +34,11 @@ export function HttpLoaderFactory(http: Http) {
 describe('FilterTextFieldComponent', () => {
   let component: FilterTextFieldComponent;
   let fixture: ComponentFixture<FilterTextFieldComponent>;
+  const filtering = {
+    filters: {
+      f: {}
+    }
+  };
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
@@ -42,9 +49,18 @@ describe('FilterTextFieldComponent', () => {
           provide: TranslateLoader,
           useFactory: HttpLoaderFactory,
           deps: [Http]
+        }),
+        StoreModule.provideStore({
+          appSettings
         })
       ],
-      providers: [FilteringService],
+      providers: [
+        AppSettingsService,
+        {
+          provide: FilteringService,
+          useValue: filtering
+        }
+      ],
       schemas: [CUSTOM_ELEMENTS_SCHEMA]
     })
     .compileComponents();
@@ -53,7 +69,10 @@ describe('FilterTextFieldComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(FilterTextFieldComponent);
     component = fixture.componentInstance;
-    component.filterInstance = {};
+    component.filterName = 'f';
+    component.form = new FormGroup({
+      f: new FormControl()
+    });
     fixture.detectChanges();
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 3f23ffd..857b511 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
@@ -15,27 +15,74 @@
  * limitations under the License.
  */
 
-import {Component, OnInit, Input} from '@angular/core';
+import {Component, AfterViewInit, Input, forwardRef} from '@angular/core';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormGroup} from 
'@angular/forms';
+import 'rxjs/add/operator/debounceTime';
 import {FilteringService} from '@app/services/filtering.service';
 
 @Component({
   selector: 'filter-text-field',
   templateUrl: './filter-text-field.component.html',
-  styleUrls: ['./filter-text-field.component.less']
+  styleUrls: ['./filter-text-field.component.less'],
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => FilterTextFieldComponent),
+      multi: true
+    }
+  ]
 })
-export class FilterTextFieldComponent implements OnInit {
+export class FilterTextFieldComponent implements AfterViewInit, 
ControlValueAccessor {
 
   constructor(private filtering: FilteringService) {
   }
 
-  ngOnInit() {
+  ngAfterViewInit() {
+    const callback = this.customOnChange ?
+      (value => this.customOnChange(value)) : (() => 
this.filtering.filteringSubject.next(null));
+    
this.form.controls[this.filterName].valueChanges.debounceTime(this.debounceInterval).subscribe(callback);
   }
 
   @Input()
-  filterInstance: any;
+  filterName: string;
 
-  onValueChange() {
-    this.filtering.filteringSubject.next(null);
+  @Input()
+  customOnChange: (value: any) => void;
+
+  @Input()
+  form: FormGroup;
+
+  private onChange: (fn: any) => void;
+
+  private readonly debounceInterval = 1500;
+
+  get filterInstance(): any {
+    return this.filtering.filters[this.filterName];
+  }
+
+  get value(): any {
+    return this.filterInstance.selectedValue;
+  }
+
+  set value(newValue: any) {
+    if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, 
newValue)) {
+      this.filterInstance.selectedValue = newValue;
+      this.onChange(newValue);
+    }
+  }
+
+  writeValue(options: any) {
+    const value = options && options.value;
+    if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, 
value)) {
+      this.filterInstance.selectedValue = value;
+    }
+  }
+
+  registerOnChange(callback: any): void {
+    this.onChange = callback;
+  }
+
+  registerOnTouched() {
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 e278a09..256b547 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,24 +15,33 @@
   limitations under the License.
 -->
 
-<div class="form-inline filter-input-container col-md-8">
-  <filter-dropdown [filterInstance]="filters.clusters"></filter-dropdown>
-  <filter-text-field [filterInstance]="filters.text"></filter-text-field>
-  <filter-dropdown [filterInstance]="filters.timeRange"></filter-dropdown>
-  <filter-dropdown [filterInstance]="filters.timeZone"></filter-dropdown>
-  <!--button class="btn btn-success" type="button">
-    <span class="fa fa-search"></span>
-  </button-->
-</div>
-<div class="default-flex col-md-4">
-  <a href="#">
-    <span class="fa fa-search-minus"></span> {{'filter.excluded' | translate}}
-  </a>
-  <menu-button [label]="filters.components.label" 
[iconClass]="filters.components.iconClass"
-               [subItems]="filters.components.options" [isFilter]="true"
-               [filterInstance]="filters.components"></menu-button>
-  <menu-button [label]="filters.levels.label" 
[iconClass]="filters.levels.iconClass"
-               [subItems]="filters.levels.options" [isFilter]="true"
-               [filterInstance]="filters.levels"></menu-button>
-  <menu-button label="filter.capture" iconClass="fa 
fa-caret-right"></menu-button>
-</div>
+<form [formGroup]="filtersForm">
+  <div class="form-inline filter-input-container col-md-8">
+    <filter-dropdown [(ngModel)]="filters.clusters.selectedValue" 
[filterName]="'clusters'"
+                     formControlName="clusters" 
[form]="filtersForm"></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'"
+                     formControlName="timeRange" 
[form]="filtersForm"></filter-dropdown>
+    <filter-dropdown [(ngModel)]="filters.timeZone.selectedValue" 
[filterName]="'timeZone'"
+                     formControlName="timeZone" [form]="filtersForm"
+                     [customOnChange]="setTimeZone"></filter-dropdown>
+    <!--button class="btn btn-success" type="button">
+      <span class="fa fa-search"></span>
+    </button-->
+  </div>
+  <div class="default-flex col-md-4">
+    <a href="#">
+      <span class="fa fa-search-minus"></span> {{'filter.excluded' | 
translate}}
+    </a>
+    <filter-button [(ngModel)]="filters.components.selectedValue" 
formControlName="components"
+                   [label]="filters.components.label" 
[iconClass]="filters.components.iconClass"
+                   [subItems]="filters.components.options" 
[filterName]="'components'"
+                   [form]="filtersForm"></filter-button>
+    <filter-button [(ngModel)]="filters.levels.selectedValue" 
formControlName="levels"
+                   [label]="filters.levels.label" 
[iconClass]="filters.levels.iconClass"
+                   [subItems]="filters.levels.options" [filterName]="'levels'"
+                   [form]="filtersForm"></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/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
index 934f37a..8291572 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
@@ -16,11 +16,13 @@
  * limitations under the License.
  */
 
-import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
+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 {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 import {FilteringService} from '@app/services/filtering.service';
 
 import {FiltersPanelComponent} from './filters-panel.component';
@@ -36,13 +38,21 @@ describe('FiltersPanelComponent', () => {
   beforeEach(async(() => {
     TestBed.configureTestingModule({
       declarations: [FiltersPanelComponent],
-      imports: [TranslateModule.forRoot({
-        provide: TranslateLoader,
-        useFactory: HttpLoaderFactory,
-        deps: [Http]
-      })],
-      providers: [FilteringService],
-      schemas: [CUSTOM_ELEMENTS_SCHEMA]
+      imports: [
+        StoreModule.provideStore({
+          appSettings
+        }),
+        TranslateModule.forRoot({
+          provide: TranslateLoader,
+          useFactory: HttpLoaderFactory,
+          deps: [Http]
+        })
+      ],
+      providers: [
+        AppSettingsService,
+        FilteringService
+      ],
+      schemas: [NO_ERRORS_SCHEMA]
     })
     .compileComponents();
   }));

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 f7b8429..b2ae9b0 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,7 +17,9 @@
  */
 
 import {Component, OnInit} from '@angular/core';
+import {FormControl, FormGroup} from '@angular/forms';
 import {FilteringService} from '@app/services/filtering.service';
+import {AppSettingsService} from '@app/services/storage/app-settings.service';
 
 @Component({
   selector: 'filters-panel',
@@ -26,7 +28,7 @@ import {FilteringService} from 
'@app/services/filtering.service';
 })
 export class FiltersPanelComponent implements OnInit {
 
-  constructor(private filtering: FilteringService) {
+  constructor(private filtering: FilteringService, private appSettings: 
AppSettingsService) {
   }
 
   ngOnInit() {
@@ -36,4 +38,16 @@ export class FiltersPanelComponent implements OnInit {
     return this.filtering.filters;
   }
 
+  private filtersFormItems = Object.keys(this.filters).reduce((currentObject, 
key) => {
+    let item = {};
+    item[key] = new FormControl();
+    return Object.assign(currentObject, item);
+  }, {});
+
+  filtersForm = new FormGroup(this.filtersFormItems);
+
+  setTimeZone(timeZone: string): void {
+    this.appSettings.setParameter('timeZone', timeZone);
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 827f63c..df72502 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
@@ -21,7 +21,7 @@
     <div [ngClass]="'col-md-1 log-status ' + log.className">{{log.level}}</div>
     <div class="col-md-3">
       <div class="log-type">{{log.type}}</div>
-      <time class="log-time">{{log.time}}</time>
+      <time class="log-time">{{log.time | amTz: filtering.timeZone | 
amDateFormat: timeFormat}}</time>
     </div>
     <div class="col-md-6 log-content-wrapper">
       <div class="collapse log-actions" [attr.id]="'details-' + i">

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 072bfcd..ea3d780 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
@@ -18,8 +18,11 @@
 import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
 import {async, ComponentFixture, TestBed} from '@angular/core/testing';
 import {StoreModule} from '@ngrx/store';
+import {MomentModule} from 'angular2-moment';
+import {MomentTimezoneModule} from 'angular-moment-timezone';
 import {AuditLogsService, auditLogs} from 
'@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from 
'@app/services/storage/service-logs.service';
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 import {HttpClientService} from '@app/services/http-client.service';
 import {FilteringService} from '@app/services/filtering.service';
 
@@ -43,8 +46,11 @@ describe('LogsListComponent', () => {
       imports: [
         StoreModule.provideStore({
           auditLogs,
-          serviceLogs
-        })
+          serviceLogs,
+          appSettings
+        }),
+        MomentModule,
+        MomentTimezoneModule
       ],
       providers: [
         {
@@ -53,6 +59,7 @@ describe('LogsListComponent', () => {
         },
         AuditLogsService,
         ServiceLogsService,
+        AppSettingsService,
         FilteringService
       ],
       schemas: [CUSTOM_ELEMENTS_SCHEMA]

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 cc77784..efa05e4 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
@@ -19,6 +19,7 @@ import {Component, OnInit, Input} from '@angular/core';
 import 'rxjs/add/operator/map';
 import {HttpClientService} from '@app/services/http-client.service';
 import {ServiceLogsService} from '@app/services/storage/service-logs.service';
+import {AppSettingsService} from '@app/services/storage/app-settings.service';
 import {FilteringService} from '@app/services/filtering.service';
 
 @Component({
@@ -28,7 +29,7 @@ import {FilteringService} from 
'@app/services/filtering.service';
 })
 export class LogsListComponent implements OnInit {
 
-  constructor(private httpClient: HttpClientService, private 
serviceLogsStorage: ServiceLogsService, private filtering: FilteringService) {
+  constructor(private httpClient: HttpClientService, private 
serviceLogsStorage: ServiceLogsService, private appSettings: 
AppSettingsService, private filtering: FilteringService) {
     this.filtering.filteringSubject.subscribe(this.loadLogs.bind(this));
   }
 
@@ -39,6 +40,8 @@ export class LogsListComponent implements OnInit {
   @Input()
   private logsArrayId: string;
 
+  timeFormat: string = 'DD/MM/YYYY HH:mm:ss';
+
   private readonly usedFilters = {
     clusters: ['clusters'],
     text: ['iMessage'],
@@ -47,14 +50,14 @@ export class LogsListComponent implements OnInit {
     levels: ['level']
   };
 
-  logs = this.serviceLogsStorage.getInstances().map(logs => {
+  logs = this.serviceLogsStorage.getAll().map(logs => {
     return logs.map(log => {
       return {
         type: log.type,
         level: log.level,
         className: log.level.toLowerCase(),
         message: log.log_message,
-        time: new Date(log.logtime).toLocaleDateString() + ' ' + new 
Date(log.logtime).toLocaleTimeString() // TODO use moment with custom time zone
+        time: log.logtime
       }
     });
   });

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 132d717..5111197 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 class="dropdown-menu" [isFilter]="isFilter" *ngIf="hasSubItems" 
[items]="subItems"
-      (selectedItemChange)="setSelectedValue($event)"></ul>
+  <ul class="dropdown-menu" *ngIf="hasSubItems" [items]="subItems" 
[isFilter]="isFilter"
+      (selectedItemChange)="isFilter && writeValue($event)"></ul>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.spec.ts
index 424d322..d53677d 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.spec.ts
@@ -39,10 +39,10 @@ describe('MenuButtonComponent', () => {
       declarations: [MenuButtonComponent],
       imports: [
         TranslateModule.forRoot({
-        provide: TranslateLoader,
-        useFactory: HttpLoaderFactory,
-        deps: [Http]
-      })],
+          provide: TranslateLoader,
+          useFactory: HttpLoaderFactory,
+          deps: [Http]
+        })],
       providers: [
         ComponentActionsService,
         FilteringService

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/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 ded01b7..08b555c 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
@@ -18,17 +18,18 @@
 
 import {Component, AfterViewInit, Input, ViewChild, ElementRef} from 
'@angular/core';
 import {ComponentActionsService} from 
'@app/services/component-actions.service';
-import {FilteringService} from '@app/services/filtering.service';
 import * as $ from 'jquery';
 
-@Component({
+export const menuButtonComponentOptions = {
   selector: 'menu-button',
   templateUrl: './menu-button.component.html',
   styleUrls: ['./menu-button.component.less']
-})
+}
+
+@Component(menuButtonComponentOptions)
 export class MenuButtonComponent implements AfterViewInit {
 
-  constructor(private actions: ComponentActionsService, private filtering: 
FilteringService) {
+  constructor(protected actions: ComponentActionsService) {
   }
 
   ngAfterViewInit() {
@@ -43,11 +44,7 @@ export class MenuButtonComponent implements AfterViewInit {
   @Input()
   action: string;
 
-  @Input()
-  isFilter: boolean;
-
-  @Input()
-  filterInstance?: any;
+  isFilter: boolean = false;
 
   @Input()
   iconClass: string;
@@ -91,12 +88,4 @@ export class MenuButtonComponent implements AfterViewInit {
     }
   }
 
-  setSelectedValue(options: any): void {
-    if (this.filterInstance.selectedValue !== options.value) {
-      this.filterInstance.selectedValue = options.value;
-      this.filterInstance.selectedLabel = options.label;
-      this.filtering.filteringSubject.next(null);
-    }
-  };
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/models/app-settings.model.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/models/app-settings.model.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/app-settings.model.ts
new file mode 100644
index 0000000..30bf0c8
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/app-settings.model.ts
@@ -0,0 +1,27 @@
+/**
+ * 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 * as moment from 'moment-timezone';
+
+export interface AppSettings {
+  timeZone: string;
+}
+
+export const defaultSettings: AppSettings = {
+  timeZone: moment.tz.guess()
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts
index 1f3a89c..c169c1b 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+import {AppSettings} from '@app/models/app-settings.model';
 import {Observable} from 'rxjs/Observable';
 import {Store, Action} from '@ngrx/store';
 import {AuditLog} from '@app/models/audit-log.model';
@@ -29,10 +30,12 @@ import {Filter} from '@app/models/filter.model';
 export const storeActions = {
   ADD: 'ADD',
   DELETE: 'DELETE',
-  CLEAR: 'CLEAR'
+  CLEAR: 'CLEAR',
+  SET: 'SET'
 };
 
 export interface AppStore {
+  appSettings: AppSettings;
   auditLogs: AuditLog[];
   serviceLogs: ServiceLog[];
   barGraphs: BarGraph[];
@@ -44,17 +47,25 @@ export interface AppStore {
 
 export class ModelService {
 
-  constructor(private modelName: string, private store: Store<AppStore>) {}
+  constructor(modelName: string, store: Store<AppStore>) {
+    this.modelName = modelName;
+    this.store = store;
+  }
+
+  protected modelName: string;
+
+  protected store: Store<AppStore>;
 
-  getInstances(): Observable<any> {
+  getAll(): Observable<any> {
     return this.store.select(this.modelName);
   }
 
+}
+
+export class CollectionModelService extends ModelService {
+
   addInstance(instance: any): void {
-    this.store.dispatch({
-      type: storeActions.ADD,
-      payload: [instance]
-    });
+    this.addInstances([instance]);
   }
 
   addInstances(instances: any[]): void {
@@ -79,7 +90,24 @@ export class ModelService {
 
 }
 
-export function reducer(state: any, action: Action): any {
+export class ObjectModelService extends ModelService {
+
+  setParameter(key: string, value: any): void {
+    let payload = {};
+    payload[key] = value;
+    this.setParameters(payload);
+  }
+
+  setParameters(params: any): void {
+    this.store.dispatch({
+      type: storeActions.SET,
+      payload: params
+    });
+  }
+
+}
+
+export function collectionReducer(state: any, action: Action): any {
   switch (action.type) {
     case storeActions.ADD:
       return [...state, ...action.payload];
@@ -93,3 +121,12 @@ export function reducer(state: any, action: Action): any {
       return state;
   }
 }
+
+export function objectReducer(state: any, action: Action): any {
+  switch (action.type) {
+    case storeActions.SET:
+      return Object.assign({}, state, action.payload);
+    default:
+      return state;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
index d471e00..a8dc017 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
@@ -17,13 +17,23 @@
  */
 
 import {TestBed, inject} from '@angular/core/testing';
+import {StoreModule} from '@ngrx/store';
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 
 import {FilteringService} from './filtering.service';
 
 describe('FilteringService', () => {
   beforeEach(() => {
     TestBed.configureTestingModule({
-      providers: [FilteringService]
+      imports: [
+        StoreModule.provideStore({
+          appSettings
+        })
+      ],
+      providers: [
+        FilteringService,
+        AppSettingsService
+      ]
     });
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts
index c4d2bdf..9f6b7dc 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts
@@ -19,13 +19,17 @@
 import {Injectable} from '@angular/core';
 import {Subject} from 'rxjs/Subject';
 import * as moment from 'moment-timezone';
+import {AppSettingsService} from '@app/services/storage/app-settings.service';
 
 @Injectable()
 export class FilteringService {
 
-  constructor() {
+  constructor(private appSettings: AppSettingsService) {
+    this.appSettings.getAll().subscribe(settings => this.timeZone = 
settings.timeZone);
   }
 
+  timeZone: string;
+
   // TODO implement loading of real options data
   filters = {
     clusters: {
@@ -57,7 +61,7 @@ export class FilteringService {
         }
       ],
       selectedValue: '',
-      selectedLabel: '',
+      selectedLabel: 'filter.all',
       paramName: 'clusters',
     },
     text: {
@@ -133,19 +137,23 @@ export class FilteringService {
           }
         }
       ],
-      selectedValue: '',
-      selectedLabel: ''
+      selectedValue: {
+        type: 'LAST',
+        unit: 'h',
+        interval: 1
+      },
+      selectedLabel: 'filter.timeRange.1hr'
     },
     timeZone: {
       options: moment.tz.names().map(zone => {
         // TODO map labels according to actual design requirements
         return {
-          label: `${zone} (${moment.tz(zone).format('Z')})`,
+          label: this.getTimeZoneLabel(zone),
           value: zone
         };
       }),
-      selectedValue: '',
-      selectedLabel: ''
+      selectedValue: moment.tz.guess(),
+      selectedLabel: this.getTimeZoneLabel(moment.tz.guess())
     },
     components: {
       label: 'filter.components',
@@ -173,7 +181,7 @@ export class FilteringService {
         }
       ],
       selectedValue: '',
-      selectedLabel: ''
+      selectedLabel: 'filter.all'
     },
     levels: {
       label: 'filter.levels',
@@ -213,7 +221,7 @@ export class FilteringService {
         }
       ],
       selectedValue: '',
-      selectedLabel: ''
+      selectedLabel: 'filter.all'
     }
   };
 
@@ -226,12 +234,10 @@ export class FilteringService {
             time = moment();
             break;
           case 'CURRENT':
-            // TODO consider user's timezone
-            time = moment().endOf(value.unit);
+            time = moment().tz(this.timeZone).endOf(value.unit);
             break;
           case 'PAST':
-            // TODO consider user's timezone
-            time = moment().startOf(value.unit).millisecond(-1);
+            time = 
moment().tz(this.timeZone).startOf(value.unit).millisecond(-1);
             break;
           default:
             break;
@@ -248,11 +254,9 @@ export class FilteringService {
             time = endTime.subtract(value.interval, value.unit);
             break;
           case 'CURRENT':
-            // TODO consider user's timezone
-            time = moment().startOf(value.unit);
+            time = moment().tz(this.timeZone).startOf(value.unit);
             break;
           case 'PAST':
-            // TODO consider user's timezone
             time = endTime.startOf(value.unit);
             break;
           default:
@@ -263,6 +267,21 @@ export class FilteringService {
     }
   };
 
+  getTimeZoneLabel(timeZone) {
+    return `${timeZone} (${moment.tz(timeZone).format('Z')})`;
+  }
+
+  valueHasChanged(currentValue: any, newValue: any): boolean {
+    if (newValue == null) {
+      return false;
+    }
+    if (typeof newValue === 'object') {
+      return JSON.stringify(currentValue) !== JSON.stringify(newValue);
+    } else {
+      return currentValue !== newValue;
+    }
+  }
+
   filteringSubject = new Subject();
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/app-settings.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/app-settings.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/app-settings.service.ts
new file mode 100644
index 0000000..1c87a3c
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/app-settings.service.ts
@@ -0,0 +1,33 @@
+/**
+ * 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 {Injectable} from '@angular/core';
+import {Action, ActionReducer, Store} from '@ngrx/store';
+import {AppSettings, defaultSettings} from '@app/models/app-settings.model';
+import {AppStore, ObjectModelService, objectReducer} from 
'@app/models/store.model';
+
+@Injectable()
+export class AppSettingsService extends ObjectModelService {
+  constructor(store: Store<AppStore>) {
+    super('appSettings', store);
+  }
+}
+
+export const appSettings: ActionReducer<AppSettings> = (state: AppSettings = 
defaultSettings, action: Action) => {
+  return objectReducer(state, action);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/audit-logs.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/audit-logs.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/audit-logs.service.ts
index 706d2f3..7c322ed 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/audit-logs.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/audit-logs.service.ts
@@ -16,19 +16,18 @@
  * limitations under the License.
  */
 
-
 import {Injectable} from '@angular/core';
 import {Action, ActionReducer, Store} from '@ngrx/store';
 import {AuditLog} from '@app/models/audit-log.model';
-import {AppStore, ModelService, reducer} from '@app/models/store.model';
+import {AppStore, CollectionModelService, collectionReducer} from 
'@app/models/store.model';
 
 @Injectable()
-export class AuditLogsService extends ModelService {
+export class AuditLogsService extends CollectionModelService {
   constructor(store: Store<AppStore>) {
     super('auditLogs', store);
   }
 }
 
 export const auditLogs: ActionReducer<AuditLog[]> = (state: AuditLog[] = [], 
action: Action) => {
-  return reducer(state, action);
+  return collectionReducer(state, action);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/bar-graphs.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/bar-graphs.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/bar-graphs.service.ts
index 2e2db5b..0109409 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/bar-graphs.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/bar-graphs.service.ts
@@ -16,19 +16,18 @@
  * limitations under the License.
  */
 
-
 import {Injectable} from '@angular/core';
 import {Action, ActionReducer, Store} from '@ngrx/store';
 import {BarGraph} from '@app/models/bar-graph.model';
-import {AppStore, ModelService, reducer} from '@app/models/store.model';
+import {AppStore, CollectionModelService, collectionReducer} from 
'@app/models/store.model';
 
 @Injectable()
-export class BarGraphsService extends ModelService {
+export class BarGraphsService extends CollectionModelService {
   constructor(store: Store<AppStore>) {
     super('barGraphs', store);
   }
 }
 
 export const barGraphs: ActionReducer<BarGraph[]> = (state: BarGraph[] = [], 
action: Action) => {
-  return reducer(state, action);
+  return collectionReducer(state, action);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/filters.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/filters.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/filters.service.ts
index 99d2140..b8748e9 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/filters.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/filters.service.ts
@@ -20,15 +20,15 @@
 import {Injectable} from '@angular/core';
 import {Action, ActionReducer, Store} from '@ngrx/store';
 import {Filter} from '@app/models/filter.model';
-import {AppStore, ModelService, reducer} from '@app/models/store.model';
+import {AppStore, CollectionModelService, collectionReducer} from 
'@app/models/store.model';
 
 @Injectable()
-export class FiltersService extends ModelService {
+export class FiltersService extends CollectionModelService {
   constructor(store: Store<AppStore>) {
     super('filters', store);
   }
 }
 
 export const filters: ActionReducer<Filter[]> = (state: Filter[] = [], action: 
Action) => {
-  return reducer(state, action);
+  return collectionReducer(state, action);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/graphs.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/graphs.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/graphs.service.ts
index 1c32d34..eda04ee 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/graphs.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/graphs.service.ts
@@ -20,15 +20,15 @@
 import {Injectable} from '@angular/core';
 import {Action, ActionReducer, Store} from '@ngrx/store';
 import {Graph} from '@app/models/graph.model';
-import {AppStore, ModelService, reducer} from '@app/models/store.model';
+import {AppStore, CollectionModelService, collectionReducer} from 
'@app/models/store.model';
 
 @Injectable()
-export class GraphsService extends ModelService {
+export class GraphsService extends CollectionModelService {
   constructor(store: Store<AppStore>) {
     super('graphs', store);
   }
 }
 
 export const graphs: ActionReducer<Graph[]> = (state: Graph[] = [], action: 
Action) => {
-  return reducer(state, action);
+  return collectionReducer(state, action);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/nodes.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/nodes.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/nodes.service.ts
index b194f94..7b2e6e9 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/nodes.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/nodes.service.ts
@@ -20,15 +20,15 @@
 import {Injectable} from '@angular/core';
 import {Action, ActionReducer, Store} from '@ngrx/store';
 import {Node} from '@app/models/node.model';
-import {AppStore, ModelService, reducer} from '@app/models/store.model';
+import {AppStore, CollectionModelService, collectionReducer} from 
'@app/models/store.model';
 
 @Injectable()
-export class NodesService extends ModelService {
+export class NodesService extends CollectionModelService {
   constructor(store: Store<AppStore>) {
     super('nodes', store);
   }
 }
 
 export const nodes: ActionReducer<Node[]> = (state: Node[] = [], action: 
Action) => {
-  return reducer(state, action);
+  return collectionReducer(state, action);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts
index 6859653..ba277c4 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts
@@ -20,15 +20,15 @@
 import {Injectable} from '@angular/core';
 import {Action, ActionReducer, Store} from '@ngrx/store';
 import {ServiceLog} from '@app/models/service-log.model';
-import {AppStore, ModelService, reducer} from '@app/models/store.model';
+import {AppStore, CollectionModelService, collectionReducer} from 
'@app/models/store.model';
 
 @Injectable()
-export class ServiceLogsService extends ModelService {
+export class ServiceLogsService extends CollectionModelService {
   constructor(store: Store<AppStore>) {
     super('serviceLogs', store);
   }
 }
 
 export const serviceLogs: ActionReducer<ServiceLog[]> = (state: ServiceLog[] = 
[], action: Action) => {
-  return reducer(state, action);
+  return collectionReducer(state, action);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/user-configs.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/user-configs.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/user-configs.service.ts
index 2c770f0..b26485d 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/user-configs.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/user-configs.service.ts
@@ -20,15 +20,15 @@
 import {Injectable} from '@angular/core';
 import {Action, ActionReducer, Store} from '@ngrx/store';
 import {UserConfig} from '@app/models/user-config.model';
-import {AppStore, ModelService, reducer} from '@app/models/store.model';
+import {AppStore, CollectionModelService, collectionReducer} from 
'@app/models/store.model';
 
 @Injectable()
-export class UserConfigsService extends ModelService {
+export class UserConfigsService extends CollectionModelService {
   constructor(store: Store<AppStore>) {
     super('userConfigs', store);
   }
 }
 
 export const userConfigs: ActionReducer<UserConfig[]> = (state: UserConfig[] = 
[], action: Action) => {
-  return reducer(state, action);
+  return collectionReducer(state, action);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/src/assets/mock-data.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/assets/mock-data.ts 
b/ambari-logsearch/ambari-logsearch-web-new/src/assets/mock-data.ts
index d269bc3..732e8d3 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/assets/mock-data.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/assets/mock-data.ts
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+import * as moment from 'moment-timezone';
+
 export const mockData = {
   login: {},
   api: {
@@ -224,7 +226,7 @@ export const mockData = {
               path: 
'/var/log/ambari-metrics-collector/ambari-metrics-collector.log',
               host: 'h0',
               level: 'WARN',
-              logtime: 1497474000000,
+              logtime: moment().valueOf(),
               ip: '192.168.0.1',
               logfile_line_number: 8,
               type: 'ams_collector',
@@ -241,14 +243,14 @@ export const mockData = {
               event_md5: '1908755391',
               event_dur_ms: 200,
               _ttl_: "+5DAYS",
-              _expire_at_: 1497906000000,
+              _expire_at_: moment().add(5, 'd').valueOf(),
               _router_field_: 20
             },
             {
               path: 
'/var/log/ambari-metrics-collector/ambari-metrics-collector.log',
               host: 'h1',
               level: 'ERROR',
-              logtime: 1497387600000,
+              logtime: moment().subtract(2, 'd'),
               ip: '192.168.0.2',
               type: 'ams_collector',
               _version_: 14,
@@ -265,14 +267,14 @@ export const mockData = {
               event_md5: '1029384756',
               event_dur_ms: 700,
               _ttl_: "+5DAYS",
-              _expire_at_: 1497819600000,
+              _expire_at_: moment().add(3, 'd').valueOf(),
               _router_field_: 5
             },
             {
               path: 
'/var/log/ambari-metrics-collector/ambari-metrics-collector.log',
               host: 'h1',
               level: 'FATAL',
-              logtime: 1497042000000,
+              logtime: moment().subtract(10, 'd').valueOf(),
               ip: '192.168.0.3',
               type: 'ambari_agent',
               _version_: 14,
@@ -289,14 +291,14 @@ export const mockData = {
               event_md5: '67589403',
               event_dur_ms: 100,
               _ttl_: "+5DAYS",
-              _expire_at_: 1497474000000,
+              _expire_at_: moment().subtract(5, 'd').valueOf(),
               _router_field_: 45
             },
             {
               path: '/var/log/ambari-metrics-collector/zookeeper-server.log',
               host: 'h1',
               level: 'INFO',
-              logtime: 1497956919700,
+              logtime: moment().subtract(25, 'h').valueOf(),
               ip: '192.168.0.4',
               type: 'zookeeper_server',
               _version_: 14,
@@ -313,14 +315,14 @@ export const mockData = {
               event_md5: '67589403',
               event_dur_ms: 1000,
               _ttl_: "+5DAYS",
-              _expire_at_: 1497956939700,
+              _expire_at_: moment().subtract(25, 'h').add(5, 'd').valueOf(),
               _router_field_: 55
             },
             {
               path: '/var/log/ambari-metrics-collector/zookeeper-server.log',
               host: 'h1',
               level: 'DEBUG',
-              logtime: 1497956919700,
+              logtime: moment().subtract(25, 'd').valueOf(),
               ip: '192.168.0.4',
               type: 'zookeeper_server',
               _version_: 14,
@@ -337,14 +339,14 @@ export const mockData = {
               event_md5: '67589403',
               event_dur_ms: 1000,
               _ttl_: "+5DAYS",
-              _expire_at_: 1497956939700,
+              _expire_at_: moment().subtract(20, 'd').valueOf(),
               _router_field_: 55
             },
             {
               path: '/var/log/ambari-metrics-collector/zookeeper-client.log',
               host: 'h1',
               level: 'TRACE',
-              logtime: 1497956919700,
+              logtime: moment().subtract(2, 'h').valueOf(),
               ip: '192.168.0.4',
               type: 'zookeeper_client',
               _version_: 14,
@@ -361,14 +363,14 @@ export const mockData = {
               event_md5: '67589403',
               event_dur_ms: 1000,
               _ttl_: "+5DAYS",
-              _expire_at_: 1497956939700,
+              _expire_at_: moment().subtract(2, 'h').add(5, 'd').valueOf(),
               _router_field_: 55
             },
             {
               path: '/var/log/ambari-metrics-collector/zookeeper-client.log',
               host: 'h1',
               level: 'UNKNOWN',
-              logtime: 1497956919700,
+              logtime: moment().subtract(31, 'd').valueOf(),
               ip: '192.168.0.4',
               type: 'zookeeper_client',
               _version_: 14,
@@ -385,7 +387,7 @@ export const mockData = {
               event_md5: '67589403',
               event_dur_ms: 1000,
               _ttl_: "+5DAYS",
-              _expire_at_: 1497956939700,
+              _expire_at_: moment().subtract(26, 'd').valueOf(),
               _router_field_: 55
             }
           ],

http://git-wip-us.apache.org/repos/asf/ambari/blob/b7edc6cf/ambari-logsearch/ambari-logsearch-web-new/yarn.lock
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/yarn.lock 
b/ambari-logsearch/ambari-logsearch-web-new/yarn.lock
index ff37374..6e592a7 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/yarn.lock
+++ b/ambari-logsearch/ambari-logsearch-web-new/yarn.lock
@@ -240,6 +240,32 @@ angular-in-memory-web-api@^0.3.1:
   version "0.3.2"
   resolved 
"https://registry.yarnpkg.com/angular-in-memory-web-api/-/angular-in-memory-web-api-0.3.2.tgz#8836d9e2534d37b728f3cb5a1caf6fe1e7fbbecd";
 
+angular-moment-timezone@^0.2.1:
+  version "0.2.1"
+  resolved 
"https://registry.yarnpkg.com/angular-moment-timezone/-/angular-moment-timezone-0.2.1.tgz#b2c1d9dd0e90558483b4da8db277bee4dbdbf6d1";
+  dependencies:
+    "@angular/common" "^4.0.0"
+    "@angular/compiler" "^4.0.0"
+    "@angular/core" "^4.0.0"
+    "@angular/forms" "^4.0.0"
+    "@angular/http" "^4.0.0"
+    "@angular/platform-browser" "^4.0.0"
+    "@angular/platform-browser-dynamic" "^4.0.0"
+    "@angular/router" "^4.0.0"
+    "@types/moment-timezone" "^0.2.34"
+    angular2-moment "^1.3.3"
+    core-js "^2.4.1"
+    moment "^2.18.1"
+    moment-timezone "^0.5.13"
+    rxjs "^5.1.0"
+    zone.js "^0.8.4"
+
+angular2-moment@^1.3.3, angular2-moment@^1.4.0:
+  version "1.4.0"
+  resolved 
"https://registry.yarnpkg.com/angular2-moment/-/angular2-moment-1.4.0.tgz#3d59c1ebc28934fcfe9b888ab461e261724987e8";
+  dependencies:
+    moment "^2.16.0"
+
 ansi-align@^2.0.0:
   version "2.0.0"
   resolved 
"https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f";
@@ -3045,7 +3071,7 @@ moment-timezone@^0.5.13:
   dependencies:
     moment ">= 2.9.0"
 
-moment@*, moment@2.18.1, "moment@>= 2.9.0", moment@>=2.14.0, moment@^2.18.1:
+moment@*, moment@2.18.1, "moment@>= 2.9.0", moment@>=2.14.0, moment@^2.16.0, 
moment@^2.18.1:
   version "2.18.1"
   resolved 
"https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f";
 

Reply via email to