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>×</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",