This is an automated email from the ASF dual-hosted git repository. sardell pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/metron.git
The following commit(s) were added to refs/heads/master by this push: new 722eb66 METRON-2211 [UI] Alerts UI should optionally render timestamp in local time (sardell) closes apache/metron#1495 722eb66 is described below commit 722eb66a6a6a1208185e238f29864d95c673f404 Author: sardell <shane.m.ard...@gmail.com> AuthorDate: Fri Sep 6 16:43:54 2019 +0200 METRON-2211 [UI] Alerts UI should optionally render timestamp in local time (sardell) closes apache/metron#1495 --- .../alerts-list/table-view/table-view.component.ts | 13 +++- .../alerts-list/tree-view/tree-view.component.ts | 6 +- .../configure-rows/configure-rows.component.html | 3 + .../configure-rows.component.spec.ts | 2 + .../alerts/configure-rows/configure-rows.module.ts | 8 ++- .../timezone-config.component.spec.ts | 76 ++++++++++++++++++++++ .../timezone-config.component.ts} | 32 ++++----- .../timezone-config.service.spec.ts | 55 ++++++++++++++++ .../timezone-config.service.ts} | 34 ++++++---- 9 files changed, 192 insertions(+), 37 deletions(-) diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts index 4092193..d0a4dc9 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts @@ -37,6 +37,8 @@ import { ConfirmationType } from 'app/model/confirmation-type'; import {HttpErrorResponse} from '@angular/common/http'; import { merge } from '../../../shared/context-menu/context-menu.util' +import * as moment from 'moment/moment'; +import { TimezoneConfigService } from 'app/alerts/configure-rows/timezone-config/timezone-config.service'; export enum MetronAlertDisplayState { COLLAPSE, EXPAND @@ -67,6 +69,7 @@ export class TableViewComponent implements OnInit, OnChanges, OnDestroy { configSubscription: Subscription; merge: Function = merge; + localTime: boolean; @Input() alerts: Alert[] = []; @Input() pagination: Pagination; @@ -85,7 +88,8 @@ export class TableViewComponent implements OnInit, OnChanges, OnDestroy { public updateService: UpdateService, public metaAlertService: MetaAlertService, public globalConfigService: GlobalConfigService, - public dialogService: DialogService) { + public dialogService: DialogService, + public timezoneConfigService: TimezoneConfigService, ) { } ngOnInit() { @@ -187,9 +191,12 @@ export class TableViewComponent implements OnInit, OnChanges, OnDestroy { } formatValue(column: ColumnMetadata, returnValue: string) { + this.localTime = this.timezoneConfigService.getTimezoneConfig(); try { - if (column.name.endsWith(':ts') || column.name.endsWith('timestamp')) { - returnValue = new Date(parseInt(returnValue, 10)).toISOString().replace('T', ' ').slice(0, 19); + if ((column.name.endsWith(':ts') || column.name.endsWith('timestamp')) && this.localTime === true) { + returnValue = moment.utc(returnValue).local().format('YYYY-MM-DD H:mm:ss'); + } else if ((column.name.endsWith(':ts') || column.name.endsWith('timestamp')) && this.localTime === false) { + returnValue = moment.utc(returnValue).format('YYYY-MM-DD H:mm:ss'); } } catch (e) {} diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts index 3bd0055..ef3cc35 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts @@ -42,6 +42,7 @@ import { AlertSource } from '../../../model/alert-source'; import { QueryBuilder } from '../query-builder'; import { GroupRequest } from 'app/model/group-request'; import { Group } from 'app/model/group'; +import { TimezoneConfigService } from 'app/alerts/configure-rows/timezone-config/timezone-config.service'; @Component({ selector: 'app-tree-view', @@ -71,8 +72,9 @@ export class TreeViewComponent extends TableViewComponent implements OnInit, OnC updateService: UpdateService, metaAlertService: MetaAlertService, globalConfigService: GlobalConfigService, - dialogService: DialogService) { - super(searchService, updateService, metaAlertService, globalConfigService, dialogService); + dialogService: DialogService, + timezoneConfigService: TimezoneConfigService, ) { + super(searchService, updateService, metaAlertService, globalConfigService, dialogService, timezoneConfigService); } addAlertChangedListner() { diff --git a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.component.html b/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.component.html index 38a0967..98c62fd 100644 --- a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.component.html +++ b/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.component.html @@ -39,6 +39,9 @@ <label> HIDE ALERT ENTRIES </label> <app-show-hide-alert-entries (changed)="configRowsChange.emit($event)" ></app-show-hide-alert-entries> + + <label class="pt-2"> TIMEZONE CONFIGURATION </label> + <app-timezone-config></app-timezone-config> </form> </div> </div> diff --git a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.component.spec.ts index 533483b..1fe95ac 100644 --- a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.component.spec.ts +++ b/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.component.spec.ts @@ -22,6 +22,7 @@ import { ConfigureRowsComponent } from './configure-rows.component'; import { ConfigureTableService } from '../../service/configure-table.service'; import { ShowHideAlertEntriesComponent } from './show-hide/show-hide-alert-entries.component'; import { SwitchComponent } from 'app/shared/switch/switch.component'; +import { TimezoneConfigComponent } from './timezone-config/timezone-config.component'; @Injectable() class ConfigureTableServiceStub {} @@ -36,6 +37,7 @@ describe('ConfigureRowsComponent', () => { ConfigureRowsComponent, ShowHideAlertEntriesComponent, SwitchComponent, + TimezoneConfigComponent, ], providers: [ { provide: ConfigureTableService, useValue: ConfigureTableServiceStub } diff --git a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts b/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts index 89585c1..9915007 100644 --- a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts +++ b/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts @@ -22,15 +22,17 @@ import { ShowHideAlertEntriesComponent } from './show-hide/show-hide-alert-entri import { SwitchModule } from 'app/shared/switch/switch.module'; import { QueryBuilder } from '../alerts-list/query-builder'; import { ShowHideService } from './show-hide/show-hide.service'; +import { TimezoneConfigComponent } from './timezone-config/timezone-config.component'; +import { TimezoneConfigService } from './timezone-config/timezone-config.service'; @NgModule({ imports: [ SharedModule, SwitchModule ], - declarations: [ ConfigureRowsComponent, ShowHideAlertEntriesComponent ], + declarations: [ ConfigureRowsComponent, ShowHideAlertEntriesComponent, TimezoneConfigComponent ], exports: [ ConfigureRowsComponent ], - providers: [ QueryBuilder, ShowHideService ], + providers: [ QueryBuilder, ShowHideService, TimezoneConfigService, ], }) export class ConfigureRowsModule { - constructor(private showHideService: ShowHideService) {} + constructor(private showHideService: ShowHideService, private timezoneConfigService: TimezoneConfigService) {} } diff --git a/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.component.spec.ts new file mode 100644 index 0000000..fd693ca --- /dev/null +++ b/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.component.spec.ts @@ -0,0 +1,76 @@ +/** + * 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 { TimezoneConfigComponent } from './timezone-config.component'; +import { SwitchComponent } from 'app/shared/switch/switch.component'; +import { TimezoneConfigService } from './timezone-config.service'; +import { By } from '@angular/platform-browser'; + +class TimezoneConfigServiceStub { + toggleUTCtoLocal(showLocal) {} +} + +describe('TimezoneConfigComponent', () => { + let component: TimezoneConfigComponent; + let fixture: ComponentFixture<TimezoneConfigComponent>; + let service: TimezoneConfigService; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + TimezoneConfigComponent, + SwitchComponent, + ], + providers: [ + { provide: TimezoneConfigService, useClass: TimezoneConfigServiceStub }, + ] + }) + .compileComponents(); + service = TestBed.get(TimezoneConfigService); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TimezoneConfigComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should toggle between UTC and Local time when clicked', () => { + spyOn(service, 'toggleUTCtoLocal'); + spyOn(component, 'toggleTimezoneConfig').and.callThrough(); + fixture.detectChanges(); + + const timeToggle = fixture.debugElement.query(By.css('[data-qe-id="UTCtoLocalToggle"] input')).nativeElement; + timeToggle.click(); + fixture.detectChanges(); + expect(timeToggle.checked).toBe(true); + expect(component.toggleTimezoneConfig).toHaveBeenCalledWith(true); + expect(service.toggleUTCtoLocal).toHaveBeenCalledWith(true); + + timeToggle.click(); + fixture.detectChanges(); + expect(timeToggle.checked).toBe(false); + expect(component.toggleTimezoneConfig).toHaveBeenCalledWith(false); + expect(component.timezoneConfigService.toggleUTCtoLocal).toHaveBeenCalledWith(false); + }); +}); diff --git a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts b/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.component.ts similarity index 51% copy from metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts copy to metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.component.ts index 89585c1..7c1436f 100644 --- a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts +++ b/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.component.ts @@ -15,22 +15,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { NgModule } from '@angular/core'; -import { SharedModule } from '../../shared/shared.module'; -import { ConfigureRowsComponent } from './configure-rows.component'; -import { ShowHideAlertEntriesComponent } from './show-hide/show-hide-alert-entries.component'; -import { SwitchModule } from 'app/shared/switch/switch.module'; -import { QueryBuilder } from '../alerts-list/query-builder'; -import { ShowHideService } from './show-hide/show-hide.service'; +import { Component } from '@angular/core'; +import { TimezoneConfigService } from './timezone-config.service'; -@NgModule({ - imports: [ SharedModule, SwitchModule ], - declarations: [ ConfigureRowsComponent, ShowHideAlertEntriesComponent ], - exports: [ ConfigureRowsComponent ], - providers: [ QueryBuilder, ShowHideService ], +@Component({ + selector: 'app-timezone-config', + template: ` + <app-switch + data-qe-id="UTCtoLocalToggle" + [text]="'Convert timestamps to local time'" + (onChange)="toggleTimezoneConfig($event)" + [selected]="timezoneConfigService.showLocal" + ></app-switch> + `, }) -export class ConfigureRowsModule { - - constructor(private showHideService: ShowHideService) {} +export class TimezoneConfigComponent { + constructor(public timezoneConfigService: TimezoneConfigService) {} + toggleTimezoneConfig(isLocal) { + this.timezoneConfigService.toggleUTCtoLocal(isLocal); + } } diff --git a/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.service.spec.ts b/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.service.spec.ts new file mode 100644 index 0000000..758336b --- /dev/null +++ b/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.service.spec.ts @@ -0,0 +1,55 @@ +/** + * 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 { TestBed } from '@angular/core/testing'; + +import { TimezoneConfigService } from './timezone-config.service'; +import { SwitchComponent } from 'app/shared/switch/switch.component'; + +describe('TimezoneConfigService', () => { + let service: TimezoneConfigService; + + beforeEach(() => { + spyOn(localStorage, 'getItem').and.returnValues('true'); + + TestBed.configureTestingModule({ + declarations: [ SwitchComponent ], + providers: [ TimezoneConfigService ] + }); + + spyOn(TimezoneConfigService.prototype, 'toggleUTCtoLocal').and.callThrough(); + service = TestBed.get(TimezoneConfigService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('should get persisted state from localStorage', () => { + expect(localStorage.getItem).toHaveBeenCalledWith(service.CONVERT_UTC_TO_LOCAL_KEY); + }); + + it('should set initial switch state', () => { + expect(service.toggleUTCtoLocal).toHaveBeenCalledWith(true); + }); + + it('should return the current timezone configuration with getTimezoneConfig()', () => { + expect(service.getTimezoneConfig()).toBe(true); + service.showLocal = false; + expect(service.getTimezoneConfig()).toBe(false); + }); +}); diff --git a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts b/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.service.ts similarity index 51% copy from metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts copy to metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.service.ts index 89585c1..db736f1 100644 --- a/metron-interface/metron-alerts/src/app/alerts/configure-rows/configure-rows.module.ts +++ b/metron-interface/metron-alerts/src/app/alerts/configure-rows/timezone-config/timezone-config.service.ts @@ -15,22 +15,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { NgModule } from '@angular/core'; -import { SharedModule } from '../../shared/shared.module'; -import { ConfigureRowsComponent } from './configure-rows.component'; -import { ShowHideAlertEntriesComponent } from './show-hide/show-hide-alert-entries.component'; -import { SwitchModule } from 'app/shared/switch/switch.module'; -import { QueryBuilder } from '../alerts-list/query-builder'; -import { ShowHideService } from './show-hide/show-hide.service'; +import { Injectable } from '@angular/core'; -@NgModule({ - imports: [ SharedModule, SwitchModule ], - declarations: [ ConfigureRowsComponent, ShowHideAlertEntriesComponent ], - exports: [ ConfigureRowsComponent ], - providers: [ QueryBuilder, ShowHideService ], +@Injectable({ + providedIn: 'root' }) -export class ConfigureRowsModule { +export class TimezoneConfigService { - constructor(private showHideService: ShowHideService) {} + public readonly CONVERT_UTC_TO_LOCAL_KEY = 'convertUTCtoLocal'; + showLocal = false; + + constructor() { + this.showLocal = localStorage.getItem(this.CONVERT_UTC_TO_LOCAL_KEY) === 'true'; + this.toggleUTCtoLocal(this.showLocal); + } + + toggleUTCtoLocal(isLocal: boolean) { + this.showLocal = isLocal; + localStorage.setItem(this.CONVERT_UTC_TO_LOCAL_KEY, isLocal.toString()); + } + + getTimezoneConfig() { + return this.showLocal; + } }