You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by sa...@apache.org on 2019/09/06 14:44:18 UTC

[metron] branch master updated: METRON-2211 [UI] Alerts UI should optionally render timestamp in local time (sardell) closes apache/metron#1495

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 <sh...@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;
+  }
 }