Repository: ambari
Updated Branches:
  refs/heads/trunk 2b9a34b0f -> 011e448e2


http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.ts
index 8544677..e021075 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.ts
@@ -16,31 +16,25 @@
  * limitations under the License.
  */
 
-import {Component, OnInit, Input, Output, EventEmitter} from '@angular/core';
+import {Component, Input} from '@angular/core';
 import * as d3 from 'd3';
-import * as moment from 'moment-timezone';
-import {AppSettingsService} from '@app/services/storage/app-settings.service';
-import {GraphComponent} from '@app/classes/components/graph/graph.component';
+import {TimeGraphComponent} from 
'@app/classes/components/graph/time-graph.component';
 import {GraphScaleItem} from '@app/classes/graph';
 
 @Component({
   selector: 'time-histogram',
   templateUrl: './time-histogram.component.html',
-  styleUrls: ['../../classes/components/graph/graph.component.less', 
'./time-histogram.component.less']
+  styleUrls: [
+    '../../classes/components/graph/graph.component.less', 
'../../classes/components/graph/time-graph.component.less',
+    './time-histogram.component.less'
+  ]
 })
-export class TimeHistogramComponent extends GraphComponent implements OnInit {
+export class TimeHistogramComponent extends TimeGraphComponent {
 
-  constructor(private appSettings: AppSettingsService) {
+  constructor() {
     super();
   }
 
-  ngOnInit() {
-    this.appSettings.getParameter('timeZone').subscribe((value: string): void 
=> {
-      this.timeZone = value;
-      this.createGraph();
-    });
-  }
-
   @Input()
   columnWidth = {
     second: 40,
@@ -50,153 +44,18 @@ export class TimeHistogramComponent extends GraphComponent 
implements OnInit {
     base: 20
   };
 
-  @Output()
-  selectArea: EventEmitter<number[]> = new EventEmitter();
-
-  readonly isTimeGraph: boolean = true;
-
-  private timeZone: string;
-
-  private dragArea: d3.Selection<SVGGraphicsElement, undefined, 
SVGGraphicsElement, undefined>;
-
-  private dragStartX: number;
-
-  private minDragX: number;
-
-  private maxDragX: number;
-
-  private readonly tickTimeFormat: string = 'MM/DD HH:mm';
-
-  private readonly historyStartEndTimeFormat: string = 'dddd, MMMM DD, YYYY';
-
-  histogram: any;
-
-  /**
-   * This property holds the data structure describing the gaps between the 
xAxis ticks.
-   * The unit property can be: second, minute, hour, day
-   * The value is the number of the given unit.
-   */
-  private chartTimeGap: {value: number, unit: string, label: string} | null;
-  /**
-   * This is the rectangle element to represent the unselected time range on 
the left side of the selected time range
-   */
-  private leftDragArea: d3.Selection<SVGGraphicsElement, undefined, 
SVGGraphicsElement, undefined>;
-  /**
-   * This is the rectangle element to represent the unselected time range on 
the right side of the selected time range
-   */
-  private rightDragArea: d3.Selection<SVGGraphicsElement, undefined, 
SVGGraphicsElement, undefined>;
-  /**
-   * This is a Date object holding the value of the first tick of the xAxis. 
It is a helper getter for the template.
-   */
-  private get firstDateTick(): Date | undefined {
-    const ticks = this.xScale && this.xScale.ticks();
-    return (ticks && ticks.length && ticks[0]) || undefined;
-  }
-  /**
-   * This is a Date object holding the value of the last tick of the xAxis. It 
is a helper getter for the template.
-   */
-  private get lastDateTick(): Date | undefined {
-    const ticks = this.xScale && this.xScale.ticks();
-    return (ticks && ticks.length && ticks[ticks.length-1]) || undefined;
-  }
-
-  protected xAxisTickFormatter = (tick: Date): string => {
-    return moment(tick).tz(this.timeZone).format(this.tickTimeFormat);
-  };
-
-  protected yAxisTickFormatter = (tick: number): string | undefined => {
-    return Number.isInteger(tick) ? tick.toFixed(0) : undefined;
-  };
-
-  /**
-   * The goal is to calculate the time gap between the given dates. It will 
return an object representing the unit and
-   * the value in the given unit. Eg.: {unit: 'minute', value: 5}
-   * @param {Date} startDate
-   * @param {Date} endDate
-   * @returns {{value: number; unit: string, label: string}}
-   */
-  private getTimeGap(startDate: Date, endDate: Date): {value: number, unit: 
string, label: string} {
-    const startDateMoment = moment(startDate);
-    const endDateMoment = moment(endDate);
-    const diffInWeek: number = endDateMoment.diff(startDateMoment, 'weeks');
-    const diffInDay: number = endDateMoment.diff(startDateMoment, 'days');
-    const diffInHour: number = endDateMoment.diff(startDateMoment, 'hours');
-    const diffInMin: number = endDateMoment.diff(startDateMoment, 'minutes');
-    const diffInSec: number = endDateMoment.diff(startDateMoment, 'seconds');
-    const value = diffInWeek >= 1 ? diffInWeek : (
-      diffInDay >= 1 ? diffInDay : (
-        diffInHour >= 1 ? diffInHour : (diffInMin >= 1 ? diffInMin : diffInSec)
-      )
-    );
-    const unit: string = diffInWeek >= 1 ? 'week' : (
-      diffInDay >= 1 ? `day` : (
-        diffInHour >= 1 ? `hour` : (diffInMin >= 1 ? `minute` : `second`)
-      )
-    );
-    const label = `histogram.gap.${unit}${value>1 ? 's' : ''}`;
-    return {
-      value,
-      unit,
-      label
-    };
-  }
-
-  /**
-   * The goal is to have a simple function to set the time gap corresponding 
to the xScale ticks.
-   * It will reset the time gap if the xScale is not set or there are no ticks.
-   */
-  private setChartTimeGapByXScale() {
-    let ticks = this.xScale && this.xScale.ticks();
-    if (ticks && ticks.length) {
-      this.setChartTimeGap(ticks[0], ticks[1] || ticks[0]);
-    } else {
-      this.resetChartTimeGap();
-    }
-  }
-
-  /**
-   * Simply reset the time gap property to null.
-   */
-  private resetChartTimeGap(): void {
-    this.chartTimeGap = null;
-  }
-
-  /**
-   * The goal is to have a single point where we set the chartTimeGap property 
corresponding the given timerange.
-   * @param {Date} startDate
-   * @param {Date} endDate
-   */
-  private setChartTimeGap(startDate: Date, endDate: Date): void {
-    this.chartTimeGap = this.getTimeGap(startDate, endDate);
-  }
-
-  /**
-   * Set the domain for the y scale regarding the given data. The maximum 
value of the data is the sum of the log level
-   * values.
-   * An example data: [{tick: 1233455677, WARN: 12, ERROR: 123}]
-   * @param {GraphScaleItem[]} data
-   */
   protected setYScaleDomain(data: GraphScaleItem[]): void {
     const keys = Object.keys(this.labels);
     const maxYValue = d3.max(data, item => keys.reduce((sum: number, key: 
string): number => sum + item[key], 0));
     this.yScale.domain([0, maxYValue]);
   }
 
-  /**
-   * Set the domain values for the x scale regarding the given data.
-   * An example data: [{tick: 1233455677, WARN: 12, ERROR: 123}]
-   * @param {GraphScaleItem[]} data
-   */
-  protected setXScaleDomain(data: GraphScaleItem[]): void {
-    this.xScale.domain(d3.extent(data, item => item.tick)).nice();
-  }
-
   protected populate(): void {
     const keys = Object.keys(this.colors);
     const data = this.data;
     const timeStamps = Object.keys(data);
     // we create a more consumable data structure for d3
-    const formattedData = timeStamps.map((timeStamp: string): {tick: number, 
[key: string]: number} => Object.assign({
+    const formattedData = timeStamps.map((timeStamp: string): GraphScaleItem 
=> Object.assign({
         tick: Number(timeStamp)
       }, data[timeStamp]));
     const layers = d3.stack().keys(keys)(formattedData);
@@ -227,92 +86,10 @@ export class TimeHistogramComponent extends GraphComponent 
implements OnInit {
         .attr('height', item => this.yScale(item[0]) - this.yScale(item[1]))
         .attr('width', columnWidth.toString())
         .style('fill', (item, index) => this.orderedColors[index])
-        .on('mouseover', this.handleRectMouseOver)
-        .on('mousemove', this.handleRectMouseMove)
-        .on('mouseout', this.handleRectMouseOut);
+        .on('mouseover', this.handleMouseOver)
+        .on('mousemove', this.handleMouseMove)
+        .on('mouseout', this.handleMouseOut);
     this.setDragBehavior();
   }
 
-  private getTimeRangeByXRanges(startX: number, endX: number): [number, 
number] {
-    const xScaleInterval = this.xScale.domain().map((point: Date): number => 
point.valueOf());
-    const xScaleLength = xScaleInterval[1] - xScaleInterval[0];
-    const ratio = xScaleLength / this.width;
-    return [Math.round(xScaleInterval[0] + ratio * startX), 
Math.round(xScaleInterval[0] + ratio * endX)];
-  }
-
-  /**
-   * The goal is to create the two shadow rectangle beside the selected area. 
Actually we blurout the not selected
-   * timeranges
-   * @param {number} startX This is the starting position of the drag event 
withing the container
-   * @param {number} currentX This is the ending point of the drag within the 
container
-   */
-  private createInvertDragArea(startX: number, currentX: number): void {
-    const height: number = this.height + this.margin.top + this.margin.bottom;
-    this.leftDragArea = this.svg.insert('rect').attr('height', 
height).attr('class', 'unselected-drag-area');
-    this.rightDragArea = this.svg.insert('rect').attr('height', 
height).attr('class', 'unselected-drag-area');
-    this.setInvertDragArea(startX, currentX);
-  }
-
-  /**
-   * Set the position and the width of the blur/shadow rectangles of the 
unselected area(s).
-   * @param {number} startX The start point of the selected area.
-   * @param {number} currentX The end point of the selected area.
-   */
-  private setInvertDragArea(startX: number, currentX: number): void {
-    const left: number = Math.min(startX, currentX);
-    const right: number = Math.max(startX, currentX);
-    const rightAreaWidth: number = Math.max(0, this.width - right);
-    const leftAreaWidth: number = Math.max(0, left);
-    this.leftDragArea.attr('x', 0).attr('width', leftAreaWidth);
-    this.rightDragArea.attr('x', right).attr('width', rightAreaWidth);
-  }
-
-  /**
-   * The goal is to have a single point where we remove the rectangles of the 
blur/shadow, unselected time range(s)
-   */
-  private clearInvertDragArea(): void {
-    this.leftDragArea.remove();
-    this.rightDragArea.remove();
-  }
-
-  private setDragBehavior(): void {
-    this.minDragX = this.margin.left;
-    this.maxDragX = this.graphContainer.clientWidth;
-    d3.selectAll(`svg#${this.svgId}`).call(d3.drag()
-      .on('start', (datum: undefined, index: number, containers: 
d3.ContainerElement[]): void => {
-        if (this.dragArea) {
-          this.dragArea.remove();
-        }
-        this.dragStartX = Math.max(0, this.getDragX(containers[0]) - 
this.margin.left);
-        this.dragArea = this.svg.insert('rect', ':first-child').attr('x', 
this.dragStartX).attr('y', 0).attr('width', 0)
-          .attr('height', this.height).attr('class', 'drag-area');
-      })
-      .on('drag', (datum: undefined, index: number, containers: 
d3.ContainerElement[]): void => {
-        const mousePos = this.getDragX(containers[0]);
-        const currentX = Math.max(mousePos, this.minDragX) - this.margin.left;
-        const startX = Math.min(currentX, this.dragStartX);
-        const currentWidth = Math.abs(currentX - this.dragStartX);
-        this.dragArea.attr('x', startX).attr('width', currentWidth);
-        let timeRange = this.getTimeRangeByXRanges(startX, startX + 
currentWidth);
-        this.setChartTimeGap(new Date(timeRange[0]), new Date(timeRange[1]));
-      })
-      .on('end', (): void => {
-        const dragAreaDetails = this.dragArea.node().getBBox();
-        const startX = Math.max(0, dragAreaDetails.x);
-        const endX = Math.min(this.width, dragAreaDetails.x + 
dragAreaDetails.width);
-        const dateRange: [number, number] = this.getTimeRangeByXRanges(startX, 
endX);
-        this.selectArea.emit(dateRange);
-        this.dragArea.remove();
-        this.setChartTimeGap(new Date(dateRange[0]), new Date(dateRange[1]));
-      })
-    );
-    d3.selectAll(`svg#${this.svgId} .value, svg#${this.svgId} 
.axis`).call(d3.drag().on('start', (): void => {
-      d3.event.sourceEvent.stopPropagation();
-    }));
-  }
-
-  private getDragX(element: d3.ContainerElement): number {
-    return d3.mouse(element)[0];
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.html
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.html
new file mode 100644
index 0000000..e2ca744
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.html
@@ -0,0 +1,27 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<div #graphContainer></div>
+<footer *ngIf="firstDateTick || lastDateTick">
+  <div *ngIf="firstDateTick">{{firstDateTick | amTz: timeZone | amDateFormat: 
historyStartEndTimeFormat}}</div>
+  <div *ngIf="lastDateTick">{{lastDateTick | amTz: timeZone | amDateFormat: 
historyStartEndTimeFormat}}</div>
+</footer>
+<graph-legend class="col-md-12" [items]="legendItems"></graph-legend>
+<graph-tooltip #tooltip [data]="tooltipInfo.data" [ngClass]="{'hide': 
!tooltipInfo.data}"
+               [style.top]="tooltipInfo.data ? tooltipPosition.top + 'px' : ''"
+               [style.left]="tooltipInfo.data ? tooltipPosition.left + 'px' : 
''"
+               [title]="tooltipInfo.title | amTz: timeZone | amDateFormat: 
tickTimeFormat"></graph-tooltip>

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.less
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.less
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.less
new file mode 100644
index 0000000..5f14eee
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.less
@@ -0,0 +1,42 @@
+/**
+ * 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';
+
+:host {
+  /deep/ .line {
+    fill: none;
+    stroke-width: 1.5px;
+  }
+
+  /deep/ .grid-line-area {
+    fill: transparent;
+
+    + .grid-line {
+      stroke: transparent;
+    }
+
+    &.visible-grid-line-area {
+      cursor: pointer;
+
+      + .grid-line {
+        stroke: @base-font-color;
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.spec.ts
new file mode 100644
index 0000000..b58717b
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.spec.ts
@@ -0,0 +1,69 @@
+/**
+ * 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 {Injector, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
+import {async, ComponentFixture, TestBed, inject} from '@angular/core/testing';
+import {MomentModule} from 'angular2-moment';
+import {MomentTimezoneModule} from 'angular-moment-timezone';
+import {TranslationModules} from '@app/test-config.spec';
+import {StoreModule} from '@ngrx/store';
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
+import {UtilsService} from '@app/services/utils.service';
+import {ServiceInjector} from '@app/classes/service-injector';
+import {GraphLegendComponent} from 
'@app/components/graph-legend/graph-legend.component';
+
+import {TimeLineGraphComponent} from './time-line-graph.component';
+
+describe('TimeLineGraphComponent', () => {
+  let component: TimeLineGraphComponent;
+  let fixture: ComponentFixture<TimeLineGraphComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [
+        TimeLineGraphComponent,
+        GraphLegendComponent
+      ],
+      imports: [
+        MomentModule,
+        MomentTimezoneModule,
+        ...TranslationModules,
+        StoreModule.provideStore({
+          appSettings
+        })
+      ],
+      providers: [
+        UtilsService,
+        AppSettingsService
+      ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(inject([Injector], (injector: Injector) => {
+    ServiceInjector.injector = injector;
+    fixture = TestBed.createComponent(TimeLineGraphComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create component', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.ts
new file mode 100644
index 0000000..2f0b450
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-line-graph/time-line-graph.component.ts
@@ -0,0 +1,111 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {Component, Input} from '@angular/core';
+import * as d3 from 'd3';
+import {GraphScaleItem, GraphLinePoint, GraphLineData} from 
'@app/classes/graph';
+import {TimeGraphComponent} from 
'@app/classes/components/graph/time-graph.component';
+
+@Component({
+  selector: 'time-line-graph',
+  templateUrl: './time-line-graph.component.html',
+  styleUrls: [
+    '../../classes/components/graph/graph.component.less', 
'../../classes/components/graph/time-graph.component.less',
+    './time-line-graph.component.less'
+  ]
+})
+export class TimeLineGraphComponent extends TimeGraphComponent {
+
+  @Input()
+  pointRadius: number = 3.5;
+
+  protected populate(): void {
+    const keys = Object.keys(this.colors),
+      data = this.data,
+      timeStamps = Object.keys(data),
+      dataForDomain = timeStamps.map((timeStamp: string): GraphScaleItem => 
Object.assign({
+        tick: Number(timeStamp)
+      }, data[timeStamp])),
+      dataForSvg = keys.map((key: string): GraphLineData => {
+        return {
+          points: timeStamps.map((timeStamp: string): GraphScaleItem => {
+            return {
+              tick: Number(timeStamp),
+              y: data[timeStamp][key]
+            };
+          }),
+          key: key
+        };
+      }),
+      line = d3.line<GraphScaleItem>().x(item => 
this.xScale(item.tick)).y(item => this.yScale(item.y));
+
+    // after we have the data we set the domain values both scales
+    this.setXScaleDomain(dataForDomain);
+    this.setYScaleDomain();
+
+    // drawing the axis
+    this.drawXAxis();
+    this.drawYAxis();
+
+    // populate the data and drawing the lines and points
+    const layer = this.svg.selectAll().data(dataForSvg);
+    layer.enter().append('path')
+      .attr('class', 'line').attr('d', (item: GraphLineData) => 
line(item.points))
+      .style('stroke', (item: GraphLineData): string => this.colors[item.key]);
+    layer.enter().append('g').selectAll('circle')
+      .data((item: GraphLineData): GraphLinePoint[] => item.points.map((point: 
GraphScaleItem): GraphLinePoint => {
+        return Object.assign({}, point, {
+          color: this.colors[item.key]
+        });
+      }))
+      .enter().append('circle')
+      .attr('cx', (item: GraphLinePoint): number => this.xScale(item.tick))
+      .attr('cy', (item: GraphLinePoint): number => this.yScale(item.y))
+      .attr('r', this.pointRadius)
+      .style('fill', (item: GraphLinePoint): string => item.color);
+    const gridLinesParent = 
this.svg.selectAll().data(dataForDomain).enter().append('g').selectAll()
+      .data((item: GraphScaleItem): GraphScaleItem[] => [item]).enter();
+    gridLinesParent.append('rect').attr('class', 'grid-line-area')
+      .attr('x', (item: GraphScaleItem): number => this.xScale(item.tick) - 
this.pointRadius).attr('y', 0)
+      .style('width', `${this.pointRadius * 2}px`).style('height', 
`${this.height}px`)
+      .on('mouseover', (d: GraphScaleItem, index: number, elements: 
HTMLElement[]): void => {
+        elements.forEach((element: HTMLElement) => 
element.classList.add('visible-grid-line-area'));
+        this.handleMouseOver(Object.assign([], d, {
+          data: d
+        }), index, elements);
+      })
+      .on('mousemove', this.handleMouseMove)
+      .on('mouseout', (d: GraphScaleItem, index: number, elements: 
HTMLElement[]): void => {
+        elements.forEach((element: HTMLElement) => 
element.classList.remove('visible-grid-line-area'));
+        this.handleMouseOut();
+      });
+    gridLinesParent.append('line').attr('class', 'grid-line')
+      .attr('x1', (item: GraphScaleItem): number => this.xScale(item.tick))
+      .attr('x2', (item: GraphScaleItem): number => this.xScale(item.tick))
+      .attr('y1', 0).attr('y2', this.height);
+    this.setDragBehavior();
+  }
+
+  protected setYScaleDomain(): void {
+    const keys = Object.keys(this.data),
+      maxValues = keys.map((currentKey: string): number => 
this.utils.getMaxNumberInObject(this.data[currentKey]), 0),
+      maximum = Math.max(...maxValues);
+    this.yScale.domain([0, maximum]);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.spec.ts
index 43e4bd5..e3034b0 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.spec.ts
@@ -27,9 +27,12 @@ import {ComponentsService, components} from 
'@app/services/storage/components.se
 import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from 
'@app/services/storage/audit-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from 
'@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from 
'@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsService, serviceLogs} from 
'@app/services/storage/service-logs.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from 
'@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from 
'@app/services/storage/service-logs-truncated.service';
 import {TabsService, tabs} from '@app/services/storage/tabs.service';
 import {HttpClientService} from '@app/services/http-client.service';
@@ -61,6 +64,7 @@ describe('TimeRangePickerComponent', () => {
           hosts,
           auditLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogs,
           serviceLogsFields,
           serviceLogsHistogramData,
@@ -82,6 +86,7 @@ describe('TimeRangePickerComponent', () => {
         HostsService,
         AuditLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/timezone-picker/timezone-picker.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/timezone-picker/timezone-picker.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/timezone-picker/timezone-picker.component.spec.ts
index ab56589..1772ec0 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/timezone-picker/timezone-picker.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/timezone-picker/timezone-picker.component.spec.ts
@@ -26,9 +26,12 @@ import {ComponentsService, components} from 
'@app/services/storage/components.se
 import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from 
'@app/services/storage/audit-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from 
'@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from 
'@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsService, serviceLogs} from 
'@app/services/storage/service-logs.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from 
'@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from 
'@app/services/storage/service-logs-truncated.service';
 import {TabsService, tabs} from '@app/services/storage/tabs.service';
 import {ComponentActionsService} from 
'@app/services/component-actions.service';
@@ -68,6 +71,7 @@ describe('TimeZonePickerComponent', () => {
           hosts,
           auditLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogs,
           serviceLogsFields,
           serviceLogsHistogramData,
@@ -84,6 +88,7 @@ describe('TimeZonePickerComponent', () => {
         HostsService,
         AuditLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.spec.ts
index ba5b613..ce4fa1c 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.spec.ts
@@ -24,6 +24,7 @@ import {TranslationModules} from '@app/test-config.spec';
 import {AuditLogsService, auditLogs} from 
'@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from 
'@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from 
'@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from 
'@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
 import {
   ServiceLogsHistogramDataService, serviceLogsHistogramData
@@ -60,6 +61,7 @@ describe('TopMenuComponent', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           serviceLogsTruncated,
@@ -82,6 +84,7 @@ describe('TopMenuComponent', () => {
         AuditLogsService,
         ServiceLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
         ServiceLogsTruncatedService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts 
b/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts
index aa86f4f..1e1246b 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts
@@ -128,28 +128,44 @@ export const mockData = {
               {
                 dataCount: [
                   {
-                    name: 'n0',
-                    value: 1
+                    name: currentTime.toISOString(),
+                    value: '75'
                   },
                   {
-                    name: 'n1',
-                    value: 2
+                    name: currentTime.clone().subtract(20, 'm').toISOString(),
+                    value: '100'
+                  },
+                  {
+                    name: currentTime.clone().subtract(40, 'm').toISOString(),
+                    value: '75'
+                  },
+                  {
+                    name: currentTime.clone().subtract(1, 'h').toISOString(),
+                    value: '50'
                   }
                 ],
-                name: 'graph0'
+                name: 'AMBARI'
               },
               {
                 dataCount: [
                   {
-                    name: 'n2',
-                    value: 10
+                    name: currentTime.toISOString(),
+                    value: '150'
                   },
                   {
-                    name: 'n3',
-                    value: 20
+                    name: currentTime.clone().subtract(20, 'm').toISOString(),
+                    value: '50'
+                  },
+                  {
+                    name: currentTime.clone().subtract(40, 'm').toISOString(),
+                    value: '75'
+                  },
+                  {
+                    name: currentTime.clone().subtract(1, 'h').toISOString(),
+                    value: '100'
                   }
                 ],
-                name: 'graph1'
+                name: 'HDFS'
               }
             ]
           },

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts
index c2cee8d..952c542 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts
@@ -27,8 +27,11 @@ import {HostsService, hosts} from 
'@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from 
'@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from 
'@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from 
'@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from 
'@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from 
'@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {ServiceLogsTruncatedService, serviceLogsTruncated} from 
'@app/services/storage/service-logs-truncated.service';
 import {TabsService, tabs} from '@app/services/storage/tabs.service';
 import {HttpClientService} from '@app/services/http-client.service';
@@ -59,6 +62,7 @@ describe('ComponentActionsService', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           serviceLogsTruncated,
@@ -76,6 +80,7 @@ describe('ComponentActionsService', () => {
         AuditLogsService,
         ServiceLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
         ServiceLogsTruncatedService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts
index 3f65cd1..a8ab5e8 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts
@@ -23,8 +23,11 @@ import {HostsService, hosts} from 
'@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from 
'@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from 
'@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from 
'@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from 
'@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from 
'@app/services/storage/service-logs-histogram-data.service';
+import {
+  ServiceLogsHistogramDataService, serviceLogsHistogramData
+} from '@app/services/storage/service-logs-histogram-data.service';
 import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 import {AppStateService, appState} from 
'@app/services/storage/app-state.service';
 import {ClustersService, clusters} from 
'@app/services/storage/clusters.service';
@@ -53,6 +56,7 @@ describe('ComponentGeneratorService', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           appSettings,
@@ -75,6 +79,7 @@ describe('ComponentGeneratorService', () => {
         AuditLogsService,
         ServiceLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
         AppSettingsService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/services/http-client.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/http-client.service.ts 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/http-client.service.ts
index 6f98bf5..1650d90 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/http-client.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/http-client.service.ts
@@ -24,6 +24,7 @@ import {
 } from '@angular/http';
 import {HomogeneousObject} from '@app/classes/object';
 import {AuditLogsListQueryParams} from 
'@app/classes/queries/audit-logs-query-params';
+import {AuditLogsGraphQueryParams} from 
'@app/classes/queries/audit-logs-graph-query-params';
 import {AuditLogsTopResourcesQueryParams} from 
'@app/classes/queries/audit-logs-top-resources-query-params';
 import {ServiceLogsQueryParams} from 
'@app/classes/queries/service-logs-query-params';
 import {ServiceLogsHistogramQueryParams} from 
'@app/classes/queries/service-logs-histogram-query-params';
@@ -47,6 +48,10 @@ export class HttpClientService extends Http {
       url: 'audit/logs',
       params: opts => new AuditLogsListQueryParams(opts)
     },
+    auditLogsGraph: {
+      url: 'audit/logs/bargraph',
+      params: opts => new AuditLogsGraphQueryParams(opts)
+    },
     auditLogsFields: {
       url: 'audit/logs/schema/fields'
     },

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts
index acdc0c2..5961309 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts
@@ -22,6 +22,7 @@ import {StoreModule} from '@ngrx/store';
 import {AuditLogsService, auditLogs} from 
'@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from 
'@app/services/storage/service-logs.service';
 import {AuditLogsFieldsService, auditLogsFields} from 
'@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService, auditLogsGraphData} from 
'@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsFieldsService, serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
 import {
   ServiceLogsHistogramDataService, serviceLogsHistogramData
@@ -55,6 +56,7 @@ describe('LogsContainerService', () => {
           auditLogs,
           serviceLogs,
           auditLogsFields,
+          auditLogsGraphData,
           serviceLogsFields,
           serviceLogsHistogramData,
           appSettings,
@@ -71,6 +73,7 @@ describe('LogsContainerService', () => {
         AuditLogsService,
         ServiceLogsService,
         AuditLogsFieldsService,
+        AuditLogsGraphDataService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
         AppSettingsService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
index 78bcdb1..4c8f2a3 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
@@ -30,6 +30,7 @@ import * as moment from 'moment-timezone';
 import {HttpClientService} from '@app/services/http-client.service';
 import {AuditLogsService} from '@app/services/storage/audit-logs.service';
 import {AuditLogsFieldsService} from 
'@app/services/storage/audit-logs-fields.service';
+import {AuditLogsGraphDataService} from 
'@app/services/storage/audit-logs-graph-data.service';
 import {ServiceLogsService} from '@app/services/storage/service-logs.service';
 import {ServiceLogsFieldsService} from 
'@app/services/storage/service-logs-fields.service';
 import {ServiceLogsHistogramDataService} from 
'@app/services/storage/service-logs-histogram-data.service';
@@ -61,13 +62,13 @@ import {CommonEntry} from 
'@app/classes/models/common-entry';
 export class LogsContainerService {
 
   constructor(
-    private httpClient: HttpClientService, private appState: AppStateService,
-    private appSettings: AppSettingsService, private auditLogsStorage: 
AuditLogsService,
-    private auditLogsFieldsStorage: AuditLogsFieldsService, private 
serviceLogsStorage: ServiceLogsService,
-    private serviceLogsFieldsStorage: ServiceLogsFieldsService, private 
tabsStorage: TabsService,
+    private httpClient: HttpClientService, private tabsStorage: TabsService, 
private componentsStorage: ComponentsService,
+    private hostsStorage: HostsService, private appState: AppStateService, 
private auditLogsStorage: AuditLogsService,
+    private auditLogsGraphStorage: AuditLogsGraphDataService, private 
auditLogsFieldsStorage: AuditLogsFieldsService,
+    private serviceLogsStorage: ServiceLogsService, private 
serviceLogsFieldsStorage: ServiceLogsFieldsService,
     private serviceLogsHistogramStorage: ServiceLogsHistogramDataService, 
private clustersStorage: ClustersService,
-    private componentsStorage: ComponentsService, private hostsStorage: 
HostsService,
-    private serviceLogsTruncatedStorage: ServiceLogsTruncatedService
+    private serviceLogsTruncatedStorage: ServiceLogsTruncatedService, private 
appSettings: AppSettingsService
+
   ) {
     const formItems = Object.keys(this.filters).reduce((currentObject: any, 
key: string): HomogeneousObject<FormControl> => {
       let formControl = new FormControl(),
@@ -498,7 +499,7 @@ export class LogsContainerService {
     query: ['includeQuery', 'excludeQuery']
   };
 
-  private readonly histogramFilters = {
+  private readonly graphFilters = {
     clusters: ['clusters'],
     timeRange: ['to', 'from'],
     components: ['mustBe'],
@@ -518,7 +519,9 @@ export class LogsContainerService {
       // TODO add all the required fields
       listFilters: ['clusters', 'timeRange', 'auditLogsSorting', 'pageSize', 
'page', 'query'],
       topResourcesFilters: ['clusters', 'timeRange', 'query'],
-      histogramFilters: ['clusters', 'timeRange', 'query']
+      graphFilters: ['clusters', 'timeRange', 'query'],
+      graphRequestName: 'auditLogsGraph',
+      graphModel: this.auditLogsGraphStorage
     },
     serviceLogs: {
       logsModel: this.serviceLogsStorage,
@@ -526,7 +529,9 @@ export class LogsContainerService {
       listFilters: [
         'clusters', 'timeRange', 'components', 'levels', 'hosts', 
'serviceLogsSorting', 'pageSize', 'page', 'query'
       ],
-      histogramFilters: ['clusters', 'timeRange', 'components', 'levels', 
'hosts', 'query']
+      graphFilters: ['clusters', 'timeRange', 'components', 'levels', 'hosts', 
'query'],
+      graphRequestName: 'serviceLogsHistogram',
+      graphModel: this.serviceLogsHistogramStorage
     }
   };
 
@@ -645,19 +650,17 @@ export class LogsContainerService {
         this.totalCount = count;
       }
     });
-    if (logsType === 'serviceLogs') {
-      // TODO rewrite to implement conditional data loading for service logs 
histogram or audit logs graph
-      this.httpClient.get('serviceLogsHistogram', 
this.getParams('histogramFilters')).subscribe((response: Response): void => {
-        const jsonResponse = response.json();
-        this.serviceLogsHistogramStorage.clear();
-        if (jsonResponse) {
-          const histogramData = jsonResponse.graphData;
-          if (histogramData) {
-            this.serviceLogsHistogramStorage.addInstances(histogramData);
-          }
+    this.httpClient.get(this.logsTypeMap[logsType].graphRequestName, 
this.getParams('graphFilters')).subscribe((response: Response): void => {
+      const jsonResponse = response.json(),
+        model = this.logsTypeMap[logsType].graphModel;
+      model.clear();
+      if (jsonResponse) {
+        const graphData = jsonResponse.graphData;
+        if (graphData) {
+          model.addInstances(graphData);
         }
-      });
-    }
+      }
+    });
     if (logsType === 'auditLogs') {
       this.httpClient.get('topAuditLogsResources', 
this.getParams('topResourcesFilters', {
         field: 'resource'
@@ -752,21 +755,23 @@ export class LogsContainerService {
     return Object.assign({}, params, additionalParams);
   }
 
-  getHistogramData(data: BarGraph[]): 
HomogeneousObject<HomogeneousObject<number>> {
-    let histogramData = {};
+  getGraphData(data: BarGraph[], keys?: string[]): 
HomogeneousObject<HomogeneousObject<number>> {
+    let graphData = {};
     data.forEach(type => {
       const name = type.name;
       type.dataCount.forEach(entry => {
         const timeStamp = new Date(entry.name).valueOf();
-        if (!histogramData[timeStamp]) {
+        if (!graphData[timeStamp]) {
           let initialValue = {};
-          Object.keys(this.colors).forEach(key => initialValue[key] = 0);
-          histogramData[timeStamp] = initialValue;
+          if (keys) {
+            keys.forEach((key: string) => initialValue[key] = 0);
+          }
+          graphData[timeStamp] = initialValue;
         }
-        histogramData[timeStamp][name] = Number(entry.value);
+        graphData[timeStamp][name] = Number(entry.value);
       });
     });
-    return histogramData;
+    return graphData;
   }
 
   loadColumnsNames(): void {

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/services/storage/audit-logs-graph-data.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/storage/audit-logs-graph-data.service.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/storage/audit-logs-graph-data.service.ts
new file mode 100644
index 0000000..eeb2780
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/storage/audit-logs-graph-data.service.ts
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {Injectable} from '@angular/core';
+import {Store} from '@ngrx/store';
+import {AppStore, CollectionModelService, getCollectionReducer} from 
'@app/classes/models/store';
+
+export const modelName = 'auditLogsGraphData';
+
+@Injectable()
+export class AuditLogsGraphDataService extends CollectionModelService {
+  constructor(store: Store<AppStore>) {
+    super(modelName, store);
+  }
+}
+
+export const auditLogsGraphData = getCollectionReducer(modelName);

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/app/services/storage/reducers.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/storage/reducers.service.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/storage/reducers.service.ts
index d700b16..3f54625 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/storage/reducers.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/storage/reducers.service.ts
@@ -30,6 +30,7 @@ import {serviceLogsHistogramData} from 
'@app/services/storage/service-logs-histo
 import {serviceLogsTruncated} from 
'@app/services/storage/service-logs-truncated.service';
 import {serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
 import {auditLogsFields} from 
'@app/services/storage/audit-logs-fields.service';
+import {auditLogsGraphData} from 
'@app/services/storage/audit-logs-graph-data.service';
 import {userConfigs} from '@app/services/storage/user-configs.service';
 import {tabs} from '@app/services/storage/tabs.service';
 
@@ -37,6 +38,7 @@ export const reducers = {
   appSettings,
   appState,
   auditLogs,
+  auditLogsGraphData,
   serviceLogs,
   serviceLogsHistogramData,
   serviceLogsTruncated,

http://git-wip-us.apache.org/repos/asf/ambari/blob/011e448e/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json 
b/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json
index 48c1d88..923160a 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json
+++ b/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json
@@ -161,6 +161,7 @@
   "logs.showGraph": "Show Graph",
   "logs.topUsers": "Top {{number}} Users",
   "logs.topResources": "Top {{number}} Resources",
+  "logs.duration": "Duration",
 
   "histogram.gap": "gap",
   "histogram.gaps": "gaps",

Reply via email to