AMBARI-21783 Log Search UI: implement timezone picker. (ababiichuk)

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

Branch: refs/heads/branch-feature-logsearch-ui
Commit: 01a3bc7af63178af3032d868d80794fda0a0185e
Parents: f3c1039
Author: ababiichuk <ababiic...@hortonworks.com>
Authored: Tue Aug 22 20:46:01 2017 +0300
Committer: ababiichuk <ababiic...@hortonworks.com>
Committed: Tue Aug 22 20:46:01 2017 +0300

----------------------------------------------------------------------
 .../src/app/app.module.ts                       |   9 +-
 .../src/app/components/app.component.html       |   1 -
 .../src/app/components/app.component.ts         |   4 +-
 .../filters-panel/filters-panel.component.html  |   3 +-
 .../filters-panel/filters-panel.component.less  |   2 +-
 .../filters-panel/filters-panel.component.ts    |   4 -
 .../login-form/login-form.component.ts          |   2 +-
 .../logs-container/logs-container.component.ts  |   2 +-
 .../main-container/main-container.component.ts  |   4 +-
 .../app/components/modal/modal.component.html   |  40 ++++++
 .../components/modal/modal.component.spec.ts    |  57 +++++++++
 .../src/app/components/modal/modal.component.ts | 122 +++++++++++++++++++
 .../time-histogram/time-histogram.component.ts  |   2 +-
 .../timezone-picker.component.html              |  26 ++++
 .../timezone-picker.component.less              |  45 +++++++
 .../timezone-picker.component.spec.ts           |  73 +++++++++++
 .../timezone-picker.component.ts                |  77 ++++++++++++
 .../src/app/components/variables.less           |   2 +
 .../src/app/mock-data.ts                        |   4 +-
 .../src/app/pipes/timezone-abbr.pipe.spec.ts    |  26 ++++
 .../src/app/pipes/timezone-abbr.pipe.ts         |  31 +++++
 .../src/app/services/filtering.service.ts       |  21 +---
 .../src/app/services/utils.service.ts           |   5 -
 .../src/assets/i18n/en.json                     |   3 +
 .../src/vendor/js/WorldMapGenerator.min.js      |  11 ++
 .../ambari-logsearch-web-new/tsconfig.json      |   3 +
 26 files changed, 539 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/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 775ac55..b883c75 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
@@ -66,6 +66,10 @@ import {PaginationComponent} from 
'@app/components/pagination/pagination.compone
 import {PaginationControlsComponent} from 
'@app/components/pagination-controls/pagination-controls.component';
 import {TimeHistogramComponent} from 
'@app/components/time-histogram/time-histogram.component';
 import {LogsContainerComponent} from 
'@app/components/logs-container/logs-container.component';
+import {ModalComponent} from '@app/components/modal/modal.component';
+import {TimeZonePickerComponent} from 
'@app/components/timezone-picker/timezone-picker.component';
+
+import {TimeZoneAbbrPipe} from '@app/pipes/timezone-abbr.pipe';
 
 export function HttpLoaderFactory(http: Http) {
   // adding 'static' parameter to step over mock data request
@@ -105,7 +109,10 @@ export function getXHRBackend(injector: Injector, browser: 
BrowserXhr, xsrf: XSR
     PaginationComponent,
     PaginationControlsComponent,
     TimeHistogramComponent,
-    LogsContainerComponent
+    LogsContainerComponent,
+    ModalComponent,
+    TimeZonePickerComponent,
+    TimeZoneAbbrPipe
   ],
   imports: [
     BrowserModule,

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/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 a353f4d..a0444c9 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,7 +24,6 @@
   </nav>
 </header>
 
-
 <main-container>
   <ng-template>
     <!-- hidden element for moving the main bar outside the fixed header -->

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.ts 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.ts
index 1622f7c..4de47ea 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/app.component.ts
@@ -30,8 +30,8 @@ import {HttpClientService} from 
'@app/services/http-client.service';
 export class AppComponent {
 
   constructor(private httpClient: HttpClientService, private translate: 
TranslateService, private appState: AppStateService) {
-    this.appState.getParameter('isAuthorized').subscribe(value => 
this.isAuthorized = value);
-    this.appState.setParameter('isInitialLoading', true);
+    appState.getParameter('isAuthorized').subscribe(value => this.isAuthorized 
= value);
+    appState.setParameter('isInitialLoading', true);
     this.httpClient.get('status').subscribe(() => this.appState.setParameters({
       isAuthorized: true,
       isInitialLoading: false

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/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 4f751fd..80f5c0f 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
@@ -23,8 +23,7 @@
                        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>
+    <timezone-picker></timezone-picker>
     <!--button class="btn btn-success" type="button">
       <span class="fa fa-search"></span>
     </button-->

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/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 6b18e91..9ab09ef 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
@@ -32,7 +32,7 @@
       border-bottom-left-radius: 0;
     }
 
-    filter-dropdown, dropdown-button {
+    filter-dropdown, dropdown-button, timezone-picker {
       border: @input-border;
 
       &:not(:last-child) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/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 b145a94..449a2e5 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
@@ -39,10 +39,6 @@ export class FiltersPanelComponent {
     return this.filtering.filters;
   }
 
-  get timeZoneSelection(): any {
-    return this.filtering.timeZoneSelection;
-  }
-
   private loadClusters(): void {
     this.httpClient.get('clusters').subscribe(response => {
       const clusterNames = response.json();

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/login-form/login-form.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/login-form/login-form.component.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/login-form/login-form.component.ts
index 62c71f1..2bc45404 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/login-form/login-form.component.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/login-form/login-form.component.ts
@@ -29,7 +29,7 @@ import {AppStateService} from 
'@app/services/storage/app-state.service';
 export class LoginFormComponent {
 
   constructor(private httpClient: HttpClientService, private appState: 
AppStateService) {
-    this.appState.getParameter('isLoginInProgress').subscribe(value => 
this.isLoginInProgress = value);
+    appState.getParameter('isLoginInProgress').subscribe(value => 
this.isLoginInProgress = value);
   }
 
   username: string;

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.ts
index c77fa5c..517db98 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.ts
@@ -40,7 +40,7 @@ import {LogField} from '@app/models/log-field.model';
 export class LogsContainerComponent implements OnInit {
 
   constructor(private httpClient: HttpClientService, private auditLogsStorage: 
AuditLogsService, private auditLogsFieldsStorage: AuditLogsFieldsService, 
private serviceLogsStorage: ServiceLogsService, private 
serviceLogsFieldsStorage: ServiceLogsFieldsService, private 
serviceLogsHistogramStorage: ServiceLogsHistogramDataService, private appState: 
AppStateService, private filtering: FilteringService) {
-    this.serviceLogsHistogramStorage.getAll().subscribe(data => {
+    serviceLogsHistogramStorage.getAll().subscribe(data => {
       let histogramData = {};
       data.forEach(type => {
         const name = type.name;

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/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 78df822..53d58cf 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
@@ -33,8 +33,8 @@ export class MainContainerComponent {
 
   constructor(private httpClient: HttpClientService, private appState: 
AppStateService, private auditLogsFieldsStorage: AuditLogsFieldsService, 
private serviceLogsFieldsStorage: ServiceLogsFieldsService) {
     this.loadColumnsNames();
-    this.appState.getParameter('isAuthorized').subscribe(value => 
this.isAuthorized = value);
-    this.appState.getParameter('isInitialLoading').subscribe(value => 
this.isInitialLoading = value);
+    appState.getParameter('isAuthorized').subscribe(value => this.isAuthorized 
= value);
+    appState.getParameter('isInitialLoading').subscribe(value => 
this.isInitialLoading = value);
   }
 
   @ContentChild(TemplateRef)

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.html
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.html
new file mode 100644
index 0000000..abd7bc8
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.html
@@ -0,0 +1,40 @@
+<!--
+  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.
+-->
+
+<div class="modal-backdrop in"></div>
+<div class="modal in">
+  <div [ngClass]="{'modal-dialog': true, 'modal-sm': isSmallModal, 'modal-lg': 
isLargeModal}">
+    <div class="modal-content">
+      <div *ngIf="showHeader" class="modal-header">
+        <button *ngIf="showCloseButton" type="button" class="close" 
data-dismiss="modal" (click)="onClose()">
+          <span>&times;</span>
+        </button>
+        <h4 *ngIf="title">{{title}}</h4>
+      </div>
+      <div class="modal-body">
+        <div *ngIf="bodyText">{{bodyText}}</div>
+        <ng-template *ngIf="bodyTemplate" 
[ngTemplateOutlet]="bodyTemplate"></ng-template>
+      </div>
+      <div *ngIf="showFooter" class="modal-footer">
+        <button *ngIf="showCancelButton" class="btn {{cancelButtonClassName}}"
+                (click)="onCancel()">{{cancelButtonLabel | translate}}</button>
+        <button *ngIf="showSubmitButton" class="btn {{submitButtonClassName}}"
+                (click)="onSubmit()">{{submitButtonLabel | translate}}</button>
+      </div>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.spec.ts
new file mode 100644
index 0000000..802bd13
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.spec.ts
@@ -0,0 +1,57 @@
+/**
+ * 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 {Http} from '@angular/http';
+import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
+import {TranslateHttpLoader} from '@ngx-translate/http-loader';
+
+import {ModalComponent} from './modal.component';
+
+export function HttpLoaderFactory(http: Http) {
+  return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
+}
+
+describe('ModalComponent', () => {
+  let component: ModalComponent;
+  let fixture: ComponentFixture<ModalComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ModalComponent],
+      imports: [
+        TranslateModule.forRoot({
+          provide: TranslateLoader,
+          useFactory: HttpLoaderFactory,
+          deps: [Http]
+        })
+      ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ModalComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create component', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.ts
new file mode 100644
index 0000000..32f59f6
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/modal/modal.component.ts
@@ -0,0 +1,122 @@
+/**
+ * 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, AfterViewInit, ElementRef, Input, Output, 
ContentChild, TemplateRef, EventEmitter} from '@angular/core';
+import * as $ from 'jquery';
+
+@Component({
+  selector: 'modal',
+  templateUrl: './modal.component.html'
+})
+export class ModalComponent implements OnInit, AfterViewInit {
+
+  constructor(private element: ElementRef) {
+    this.rootElement = $(this.element.nativeElement);
+  }
+
+  ngOnInit() {
+    this.modalElements = this.rootElement.find('.in');
+    this.show();
+  }
+
+  ngAfterViewInit() {
+    this.init.emit();
+  }
+
+  private rootElement: JQuery;
+
+  private modalElements: JQuery;
+
+  @Input()
+  showHeader: boolean = true;
+
+  @Input()
+  title: string = '';
+
+  @Input()
+  showCloseButton: boolean = true;
+
+  @Input()
+  bodyText: string = '';
+
+  @Input()
+  showFooter: boolean = true;
+
+  @Input()
+  showSubmitButton: boolean = true;
+
+  @Input()
+  submitButtonLabel: string = 'modal.submit';
+
+  @Input()
+  submitButtonClassName: string = 'btn-success';
+
+  @Input()
+  showCancelButton: boolean = true;
+
+  @Input()
+  cancelButtonLabel: string = 'modal.cancel';
+
+  @Input()
+  cancelButtonClassName: string = 'btn-default';
+
+  @Input()
+  isSmallModal: boolean = false;
+
+  @Input()
+  isLargeModal: boolean = false;
+
+  @ContentChild(TemplateRef)
+  bodyTemplate;
+
+  @Output()
+  init: EventEmitter<any> = new EventEmitter();
+
+  @Output()
+  submit: EventEmitter<any> = new EventEmitter();
+
+  @Output()
+  cancel: EventEmitter<any> = new EventEmitter();
+
+  @Output()
+  close: EventEmitter<any> = new EventEmitter();
+
+  show(): void {
+    this.modalElements.show();
+  }
+
+  hide(): void {
+    this.modalElements.hide();
+  }
+
+  onSubmit(): void {
+    this.hide();
+    this.submit.emit();
+  }
+
+  onCancel(): void {
+    this.hide();
+    this.cancel.emit();
+  }
+
+  onClose(): void {
+    this.hide();
+    this.close.emit();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.ts
index 1dfd1f8..7856ecc 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.ts
@@ -29,7 +29,7 @@ import {AppSettingsService} from 
'@app/services/storage/app-settings.service';
 export class TimeHistogramComponent implements OnInit, AfterViewInit, 
OnChanges {
 
   constructor(private appSettings: AppSettingsService) {
-    this.appSettings.getParameter('timeZone').subscribe(value => {
+    appSettings.getParameter('timeZone').subscribe(value => {
       this.timeZone = value;
       this.createHistogram();
     });

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.html
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.html
new file mode 100644
index 0000000..3cb196e
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.html
@@ -0,0 +1,26 @@
+<!--
+  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" (click)="setTimeZonePickerDisplay(true)">
+  {{timeZone | timeZoneAbbr}} <span class="caret"></span>
+</button>
+<modal *ngIf="isTimeZonePickerDisplayed" [showCloseButton]="false" 
[isLargeModal]="true"
+       (init)="initMap()" (cancel)="setTimeZonePickerDisplay(false)" 
(submit)="setTimeZone()">
+  <ng-template>
+    <div attr.id="{{mapElementId}}"></div>
+  </ng-template>
+</modal>

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.less
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.less
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.less
new file mode 100644
index 0000000..4fa043d
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.less
@@ -0,0 +1,45 @@
+/**
+ * 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';
+
+.btn-link {
+  // TODO implement actual colors
+  color: @submit-color;
+
+  &:hover {
+    color: @submit-hover-color;
+  }
+}
+
+/deep/ #timezone-map {
+  .Cbox {
+    .quickLink {
+      padding-top: 4px;
+    }
+  }
+
+  .hoverZone {
+    display: inline-block;
+
+    &:after {
+      content: '\007C\00a0\00a0';
+      visibility: hidden;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.spec.ts
new file mode 100644
index 0000000..0ef17de
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.spec.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 {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 {ComponentActionsService} from 
'@app/services/component-actions.service';
+import {TimeZoneAbbrPipe} from '@app/pipes/timezone-abbr.pipe';
+import {ModalComponent} from '@app/components/modal/modal.component';
+
+import {TimeZonePickerComponent} from './timezone-picker.component';
+
+export function HttpLoaderFactory(http: Http) {
+  return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
+}
+
+describe('TimeZonePickerComponent', () => {
+  let component: TimeZonePickerComponent;
+  let fixture: ComponentFixture<TimeZonePickerComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [
+        TimeZonePickerComponent,
+        ModalComponent,
+        TimeZoneAbbrPipe
+      ],
+      imports: [
+        StoreModule.provideStore({
+          appSettings
+        }),
+        TranslateModule.forRoot({
+          provide: TranslateLoader,
+          useFactory: HttpLoaderFactory,
+          deps: [Http]
+        })
+      ],
+      providers: [
+        AppSettingsService,
+        ComponentActionsService
+      ],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(TimeZonePickerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create component', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.ts
new file mode 100644
index 0000000..32f6474
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/timezone-picker/timezone-picker.component.ts
@@ -0,0 +1,77 @@
+/**
+ * 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} from '@angular/core';
+import * as $ from 'jquery';
+import '@vendor/js/WorldMapGenerator.min';
+import {AppSettingsService} from '@app/services/storage/app-settings.service';
+import {ComponentActionsService} from 
'@app/services/component-actions.service';
+
+@Component({
+  selector: 'timezone-picker',
+  templateUrl: './timezone-picker.component.html',
+  styleUrls: ['./timezone-picker.component.less']
+})
+export class TimeZonePickerComponent {
+
+  constructor(private appSettings: AppSettingsService, private actions: 
ComponentActionsService) {
+    appSettings.getParameter('timeZone').subscribe(value => this.timeZone = 
value);
+  }
+
+  readonly mapElementId = 'timezone-map';
+  
+  private readonly mapOptions = {
+    quickLink: [
+      {
+        PST: 'PST',
+        MST: 'MST',
+        CST: 'CST',
+        EST: 'EST',
+        GMT: 'GMT',
+        LONDON: 'Europe/London',
+        IST: 'IST'
+      }
+    ]
+  };
+
+  private mapElement: any;
+
+  private timeZoneSelect: JQuery;
+
+  isTimeZonePickerDisplayed: boolean = false;
+
+  timeZone: string;
+
+  setTimeZonePickerDisplay(isDisplayed: boolean): void {
+    this.isTimeZonePickerDisplayed = isDisplayed;
+  }
+
+  initMap(): void {
+    this.mapElement = $(`#${this.mapElementId}`);
+    this.mapElement.WorldMapGenerator(this.mapOptions);
+    this.timeZoneSelect = this.mapElement.find('select');
+    this.timeZoneSelect.removeClass('btn 
btn-default').addClass('form-control').val(this.timeZone);
+  }
+
+  setTimeZone(): void {
+    const timeZone = this.timeZoneSelect.val();
+    this.actions.setTimeZone(timeZone);
+    this.setTimeZonePickerDisplay(false);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/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 0d739a1..f72183c 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
@@ -41,6 +41,8 @@
 @debug-color: #65E8FF;
 @trace-color: #888;
 @unknown-color: #BDBDBD;
+@submit-color: #5CB85C;
+@submit-hover-color: #449D44;
 
 // Mixins
 .flex-vertical-align {

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts
index 1f738ae..3404a4b 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts
@@ -640,7 +640,7 @@ export const mockData = {
                     value: '1000'
                   },
                   {
-                    name: moment().add(1, 'h').toISOString(),
+                    name: moment().subtract(1, 'h').toISOString(),
                     value: '2000'
                   }
                 ],
@@ -653,7 +653,7 @@ export const mockData = {
                     value: '700'
                   },
                   {
-                    name: moment().add(1, 'h').toISOString(),
+                    name: moment().subtract(1, 'h').toISOString(),
                     value: '900'
                   }
                 ],

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/pipes/timezone-abbr.pipe.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/pipes/timezone-abbr.pipe.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/pipes/timezone-abbr.pipe.spec.ts
new file mode 100644
index 0000000..0d0c24c
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/pipes/timezone-abbr.pipe.spec.ts
@@ -0,0 +1,26 @@
+/**
+ * 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 {TimeZoneAbbrPipe} from './timezone-abbr.pipe';
+
+describe('TimeZoneAbbrPipe', () => {
+  it('create an instance', () => {
+    const pipe = new TimeZoneAbbrPipe();
+    expect(pipe).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/pipes/timezone-abbr.pipe.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/pipes/timezone-abbr.pipe.ts 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/pipes/timezone-abbr.pipe.ts
new file mode 100644
index 0000000..f4aab0b
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/pipes/timezone-abbr.pipe.ts
@@ -0,0 +1,31 @@
+/**
+ * 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 {Pipe, PipeTransform} from '@angular/core';
+import * as moment from 'moment-timezone';
+
+@Pipe({
+  name: 'timeZoneAbbr'
+})
+export class TimeZoneAbbrPipe implements PipeTransform {
+
+  transform(value: string): string {
+    return moment.tz.zone(value).abbr(moment().valueOf());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/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 9a589cc..8088872 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
@@ -22,17 +22,16 @@ import * as moment from 'moment-timezone';
 import {AppSettingsService} from '@app/services/storage/app-settings.service';
 import {ClustersService} from '@app/services/storage/clusters.service';
 import {ComponentsService} from '@app/services/storage/components.service';
-import {UtilsService} from '@app/services/utils.service';
 
 @Injectable()
 export class FilteringService {
 
-  constructor(private appSettings: AppSettingsService, private 
clustersStorage: ClustersService, private componentsStorage: ComponentsService, 
private utils: UtilsService) {
-    this.appSettings.getParameter('timeZone').subscribe(value => this.timeZone 
= value || this.defaultTimeZone);
-    this.clustersStorage.getAll().subscribe(clusters => {
+  constructor(private appSettings: AppSettingsService, private 
clustersStorage: ClustersService, private componentsStorage: ComponentsService) 
{
+    appSettings.getParameter('timeZone').subscribe(value => this.timeZone = 
value || this.defaultTimeZone);
+    clustersStorage.getAll().subscribe(clusters => {
       this.filters.clusters.options = [...this.filters.clusters.options, 
...clusters.map(this.getListItem)];
     });
-    this.componentsStorage.getAll().subscribe(components => {
+    componentsStorage.getAll().subscribe(components => {
       this.filters.components.options = [...this.filters.components.options, 
...components.map(this.getListItem)];
     });
   }
@@ -242,18 +241,6 @@ export class FilteringService {
     }
   };
 
-  timeZoneSelection = {
-    options: moment.tz.names().map(zone => {
-      // TODO map labels according to actual design requirements
-      return {
-        label: this.utils.getTimeZoneLabel(zone),
-        value: zone
-      };
-    }),
-    defaultValue: this.defaultTimeZone,
-    defaultLabel: this.utils.getTimeZoneLabel(this.defaultTimeZone)
-  };
-
   private filtersFormItems = Object.keys(this.filters).reduce((currentObject, 
key) => {
     let formControl = new FormControl(),
       item = {

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.ts 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.ts
index 2deff9e..9f6cacd 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.ts
@@ -17,7 +17,6 @@
  */
 
 import {Injectable} from '@angular/core';
-import * as moment from 'moment-timezone';
 
 @Injectable()
 export class UtilsService {
@@ -44,8 +43,4 @@ export class UtilsService {
     return valuesArray.join(',');
   }
 
-  getTimeZoneLabel(timeZone) {
-    return `${timeZone} (${moment.tz(timeZone).format('Z')})`;
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/01a3bc7a/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json 
b/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json
index 1b71f24..5c7ab8d 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json
@@ -1,6 +1,9 @@
 {
   "common.title": "Log Search",
 
+  "modal.submit": "OK",
+  "modal.cancel": "Cancel",
+
   "authorization.name": "Username",
   "authorization.password": "Password",
   "authorization.signIn": "Sign In",

Reply via email to