AMBARI-21845 Log Search UI: add filter by hostname for service logs. 
(ababiichuk)


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

Branch: refs/heads/trunk
Commit: 5f1b98589c68e0dcc069372a1b25b83506d5f120
Parents: be5fbff
Author: ababiichuk <ababiic...@hortonworks.com>
Authored: Tue Aug 29 19:09:58 2017 +0300
Committer: ababiichuk <ababiic...@hortonworks.com>
Committed: Tue Aug 29 19:09:58 2017 +0300

----------------------------------------------------------------------
 .../src/app/app.module.ts                       |  11 +-
 .../dropdown-button.component.ts                |   8 +-
 .../dropdown-list/dropdown-list.component.html  |   7 +-
 .../dropdown-list/dropdown-list.component.less  |   4 +
 .../dropdown-list.component.spec.ts             |  63 +++++++-
 .../dropdown-list/dropdown-list.component.ts    |  23 ++-
 .../filters-panel/filters-panel.component.html  |   8 +-
 .../filters-panel.component.spec.ts             |   5 +-
 .../filters-panel/filters-panel.component.ts    |  30 +---
 .../logs-container.component.html               |   4 +-
 .../logs-container.component.spec.ts            |   9 +-
 .../logs-container/logs-container.component.ts  | 162 ++++---------------
 .../logs-list/logs-list.component.html          |   2 +-
 .../logs-list/logs-list.component.spec.ts       |   5 +-
 .../menu-button/menu-button.component.html      |   3 +-
 .../menu-button/menu-button.component.ts        |   9 +-
 .../components/node-bar/node-bar.component.html |  19 +++
 .../components/node-bar/node-bar.component.less |  39 +++++
 .../node-bar/node-bar.component.spec.ts         |  43 +++++
 .../components/node-bar/node-bar.component.ts   |  35 ++++
 .../pagination/pagination.component.html        |   2 +-
 .../src/app/mock-data.ts                        | 123 ++++++++++----
 .../src/app/models/node.model.ts                |   2 +-
 .../src/app/models/store.model.ts               |   2 +-
 .../component-generator.service.spec.ts         |  84 ++++++++++
 .../app/services/component-generator.service.ts |  57 +++++++
 .../src/app/services/filtering.service.spec.ts  |  20 ++-
 .../src/app/services/filtering.service.ts       |  48 +++++-
 .../src/app/services/http-client.service.ts     |   3 +
 .../app/services/logs-container.service.spec.ts |  82 ++++++++++
 .../src/app/services/logs-container.service.ts  | 148 +++++++++++++++++
 .../src/app/services/mock-api-data.service.ts   |   4 +
 .../src/app/services/storage/hosts.service.ts   |  32 ++++
 .../src/app/services/storage/nodes.service.ts   |  32 ----
 .../app/services/storage/reducers.service.ts    |   4 +-
 .../src/assets/i18n/en.json                     |   1 +
 36 files changed, 875 insertions(+), 258 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/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 b883c75..c08cb3a 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
@@ -33,6 +33,8 @@ import {HttpClientService} from 
'@app/services/http-client.service';
 import {ComponentActionsService} from 
'@app/services/component-actions.service';
 import {FilteringService} from '@app/services/filtering.service';
 import {UtilsService} from '@app/services/utils.service';
+import {LogsContainerService} from '@app/services/logs-container.service';
+import {ComponentGeneratorService} from 
'@app/services/component-generator.service';
 
 import {AppSettingsService} from '@app/services/storage/app-settings.service';
 import {AppStateService} from '@app/services/storage/app-state.service';
@@ -40,7 +42,7 @@ import {AuditLogsService} from 
'@app/services/storage/audit-logs.service';
 import {ServiceLogsService} from '@app/services/storage/service-logs.service';
 import {ServiceLogsHistogramDataService} from 
'@app/services/storage/service-logs-histogram-data.service';
 import {GraphsService} from '@app/services/storage/graphs.service';
-import {NodesService} from '@app/services/storage/nodes.service';
+import {HostsService} from '@app/services/storage/hosts.service';
 import {UserConfigsService} from '@app/services/storage/user-configs.service';
 import {FiltersService} from '@app/services/storage/filters.service';
 import {ClustersService} from '@app/services/storage/clusters.service';
@@ -68,6 +70,7 @@ import {TimeHistogramComponent} from 
'@app/components/time-histogram/time-histog
 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 {NodeBarComponent} from '@app/components/node-bar/node-bar.component';
 
 import {TimeZoneAbbrPipe} from '@app/pipes/timezone-abbr.pipe';
 
@@ -112,6 +115,7 @@ export function getXHRBackend(injector: Injector, browser: 
BrowserXhr, xsrf: XSR
     LogsContainerComponent,
     ModalComponent,
     TimeZonePickerComponent,
+    NodeBarComponent,
     TimeZoneAbbrPipe
   ],
   imports: [
@@ -136,13 +140,15 @@ export function getXHRBackend(injector: Injector, 
browser: BrowserXhr, xsrf: XSR
     ComponentActionsService,
     FilteringService,
     UtilsService,
+    LogsContainerService,
+    ComponentGeneratorService,
     AppSettingsService,
     AppStateService,
     AuditLogsService,
     ServiceLogsService,
     ServiceLogsHistogramDataService,
     GraphsService,
-    NodesService,
+    HostsService,
     UserConfigsService,
     FiltersService,
     ClustersService,
@@ -156,6 +162,7 @@ export function getXHRBackend(injector: Injector, browser: 
BrowserXhr, xsrf: XSR
     }
   ],
   bootstrap: [AppComponent],
+  entryComponents: [NodeBarComponent],
   schemas: [CUSTOM_ELEMENTS_SCHEMA]
 })
 export class AppModule {

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
index 63103ee..5800190 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
@@ -50,16 +50,16 @@ export class DropdownButtonComponent implements OnInit {
   action?: string;
 
   @Input()
-  additionalArgs?: any[] = [];
+  additionalArgs: any[] = [];
 
   @Input()
-  isMultipleChoice?: boolean = false;
+  isMultipleChoice: boolean = false;
 
   @Input()
-  isRightAlign?: boolean = false;
+  isRightAlign: boolean = false;
 
   @Input()
-  isDropup?: boolean = false;
+  isDropup: boolean = false;
 
   protected selectedValue?: any;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.html
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.html
index d9d1de0..1baebed 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.html
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.html
@@ -19,10 +19,13 @@
   <label class="list-item-label" *ngIf="isMultipleChoice">
     <input type="checkbox" [attr.id]="item.id || item.value" 
[attr.checked]="item.isChecked ? 'checked' : null"
            (change)="changeSelectedItem({value: item.value, isChecked: 
$event.currentTarget.checked})">
-    <label [attr.for]="item.id || item.value">{{item.label | 
translate}}</label>
+    <label [attr.for]="item.id || item.value" 
class="label-container">{{item.label | translate}}
+      <div #additionalComponent></div>
+    </label>
   </label>
-  <span class="list-item-label" *ngIf="!isMultipleChoice"
+  <span class="list-item-label label-container" *ngIf="!isMultipleChoice"
         (click)="changeSelectedItem({value: item.value, label: item.label})">
     {{item.label | translate}}
+    <div #additionalComponent></div>
   </span>
 </li>

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
index 804bf48..d47160f 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.less
@@ -33,5 +33,9 @@
     input[type=checkbox]:checked + label:after {
       top: @checkbox-top;
     }
+
+    .label-container {
+      width: 100%;
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts
index e16d93a..5409d30 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts
@@ -20,6 +20,20 @@ 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 {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 {ServiceLogsFieldsService, serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
+import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from 
'@app/services/storage/service-logs-histogram-data.service';
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
+import {ClustersService, clusters} from 
'@app/services/storage/clusters.service';
+import {ComponentsService, components} from 
'@app/services/storage/components.service';
+import {ComponentGeneratorService} from 
'@app/services/component-generator.service';
+import {LogsContainerService} from '@app/services/logs-container.service';
+import {HttpClientService} from '@app/services/http-client.service';
+import {FilteringService} from '@app/services/filtering.service';
 
 import {DropdownListComponent} from './dropdown-list.component';
 
@@ -32,13 +46,52 @@ describe('DropdownListComponent', () => {
   let fixture: ComponentFixture<DropdownListComponent>;
 
   beforeEach(async(() => {
+    const httpClient = {
+      get: () => {
+        return {
+          subscribe: () => {
+          }
+        }
+      }
+    };
     TestBed.configureTestingModule({
       declarations: [DropdownListComponent],
-      imports: [TranslateModule.forRoot({
-        provide: TranslateLoader,
-        useFactory: HttpLoaderFactory,
-        deps: [Http]
-      })]
+      imports: [
+        TranslateModule.forRoot({
+          provide: TranslateLoader,
+          useFactory: HttpLoaderFactory,
+          deps: [Http]
+        }),
+        StoreModule.provideStore({
+          hosts,
+          auditLogs,
+          serviceLogs,
+          auditLogsFields,
+          serviceLogsFields,
+          serviceLogsHistogramData,
+          appSettings,
+          clusters,
+          components
+        })
+      ],
+      providers: [
+        ComponentGeneratorService,
+        LogsContainerService,
+        {
+          provide: HttpClientService,
+          useValue: httpClient
+        },
+        FilteringService,
+        HostsService,
+        AuditLogsService,
+        ServiceLogsService,
+        AuditLogsFieldsService,
+        ServiceLogsFieldsService,
+        ServiceLogsHistogramDataService,
+        AppSettingsService,
+        ClustersService,
+        ComponentsService
+      ]
     })
     .compileComponents();
   }));

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts
index 555e4a8..3de664e 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts
@@ -16,14 +16,25 @@
  * limitations under the License.
  */
 
-import {Component, Input, Output, EventEmitter} from '@angular/core';
+import {Component, AfterViewInit, Input, Output, EventEmitter, ViewChildren, 
ViewContainerRef, QueryList} from '@angular/core';
+import {ComponentGeneratorService} from 
'@app/services/component-generator.service';
 
 @Component({
   selector: 'ul[data-component="dropdown-list"]',
   templateUrl: './dropdown-list.component.html',
   styleUrls: ['./dropdown-list.component.less']
 })
-export class DropdownListComponent {
+export class DropdownListComponent implements AfterViewInit {
+
+  constructor(private componentGenerator: ComponentGeneratorService) {
+  }
+
+  ngAfterViewInit() {
+    const setter = this.additionalLabelComponentSetter;
+    if (setter) {
+      this.containers.forEach((container, index) => 
this.componentGenerator[setter](this.items[index].value, container));
+    }
+  }
 
   @Input()
   items: any[];
@@ -34,9 +45,17 @@ export class DropdownListComponent {
   @Input()
   isMultipleChoice?: boolean = false;
 
+  @Input()
+  additionalLabelComponentSetter?: string;
+
   @Output()
   selectedItemChange: EventEmitter<any> = new EventEmitter();
 
+  @ViewChildren('additionalComponent', {
+    read: ViewContainerRef
+  })
+  containers: QueryList<ViewContainerRef>;
+
   changeSelectedItem(options: any): void {
     this.selectedItemChange.emit(options);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/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 80f5c0f..6df6988 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
@@ -32,11 +32,15 @@
     <a href="#">
       <span class="fa fa-search-minus"></span> {{'filter.excluded' | 
translate}}
     </a>
+    <filter-button formControlName="hosts" [label]="filters.hosts.label"
+                   [iconClass]="filters.hosts.iconClass" 
[subItems]="filters.hosts.options"
+                   [isMultipleChoice]="true" [isRightAlign]="true"
+                   
additionalLabelComponentSetter="getDataForHostsNodeBar"></filter-button>
     <filter-button formControlName="components" 
[label]="filters.components.label"
                    [iconClass]="filters.components.iconClass" 
[subItems]="filters.components.options"
-                   [isMultipleChoice]="true" 
isRightAlign="true"></filter-button>
+                   [isMultipleChoice]="true" 
[isRightAlign]="true"></filter-button>
     <filter-button formControlName="levels" [label]="filters.levels.label" 
[iconClass]="filters.levels.iconClass"
-                   [subItems]="filters.levels.options" 
[isMultipleChoice]="true" isRightAlign="true"></filter-button>
+                   [subItems]="filters.levels.options" 
[isMultipleChoice]="true" [isRightAlign]="true"></filter-button>
     <menu-button label="filter.capture" iconClass="fa 
fa-caret-right"></menu-button>
   </div>
 </form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
index c0234bb..b1cf990 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
@@ -25,6 +25,7 @@ import {StoreModule} from '@ngrx/store';
 import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 import {ClustersService, clusters} from 
'@app/services/storage/clusters.service';
 import {ComponentsService, components} from 
'@app/services/storage/components.service';
+import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {FilteringService} from '@app/services/filtering.service';
 import {HttpClientService} from '@app/services/http-client.service';
 import {UtilsService} from '@app/services/utils.service';
@@ -54,7 +55,8 @@ describe('FiltersPanelComponent', () => {
         StoreModule.provideStore({
           appSettings,
           clusters,
-          components
+          components,
+          hosts
         }),
         TranslateModule.forRoot({
           provide: TranslateLoader,
@@ -66,6 +68,7 @@ describe('FiltersPanelComponent', () => {
         AppSettingsService,
         ClustersService,
         ComponentsService,
+        HostsService,
         FilteringService,
         {
           provide: HttpClientService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/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 449a2e5..e407021 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
@@ -19,9 +19,6 @@
 import {Component} from '@angular/core';
 import {FormGroup} from '@angular/forms';
 import {FilteringService} from '@app/services/filtering.service';
-import {HttpClientService} from '@app/services/http-client.service';
-import {ClustersService} from '@app/services/storage/clusters.service';
-import {ComponentsService} from '@app/services/storage/components.service';
 
 @Component({
   selector: 'filters-panel',
@@ -30,35 +27,16 @@ import {ComponentsService} from 
'@app/services/storage/components.service';
 })
 export class FiltersPanelComponent {
 
-  constructor(private filtering: FilteringService, private httpClient: 
HttpClientService, private clustersStorage: ClustersService, private 
componentsStorage: ComponentsService) {
-    this.loadClusters();
-    this.loadComponents();
+  constructor(private filtering: FilteringService) {
+    this.filtering.loadClusters();
+    this.filtering.loadComponents();
+    this.filtering.loadHosts();
   }
 
   get filters(): any {
     return this.filtering.filters;
   }
 
-  private loadClusters(): void {
-    this.httpClient.get('clusters').subscribe(response => {
-      const clusterNames = response.json();
-      if (clusterNames) {
-        this.clustersStorage.addInstances(clusterNames);
-      }
-    });
-  }
-
-  private loadComponents(): void {
-    this.httpClient.get('components').subscribe(response => {
-      const jsonResponse = response.json(),
-        components = jsonResponse && jsonResponse.groupList;
-      if (components) {
-        const componentNames = components.map(component => component.type);
-        this.componentsStorage.addInstances(componentNames);
-      }
-    });
-  }
-
   get filtersForm(): FormGroup {
     return this.filtering.filtersForm;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.html
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.html
index 2e642be..a43f6c0 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.html
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.html
@@ -16,7 +16,7 @@
 -->
 
 <time-histogram class="col-md-12" [data]="histogramData" 
[customOptions]="histogramOptions"></time-histogram>
-<dropdown-button class="pull-right" label="logs.columns" 
[options]="availableColumns | async" isRightAlign="true"
+<dropdown-button class="pull-right" label="logs.columns" 
[options]="availableColumns | async" [isRightAlign]="true"
                  isMultipleChoice="true" action="updateSelectedColumns"
-                 
[additionalArgs]="this[this.logsTypeMapObject.fieldsModel]"></dropdown-button>
+                 
[additionalArgs]="logsTypeMapObject.fieldsModel"></dropdown-button>
 <logs-list [logs]="logs | async" [totalCount]="totalCount" 
[displayedColumns]="displayedColumns"></logs-list>

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.spec.ts
index 7b5169b..30c6a33 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.spec.ts
@@ -28,9 +28,11 @@ import {AuditLogsFieldsService, auditLogsFields} from 
'@app/services/storage/aud
 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 {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {HttpClientService} from '@app/services/http-client.service';
 import {FilteringService} from '@app/services/filtering.service';
 import {UtilsService} from '@app/services/utils.service';
+import {LogsContainerService} from '@app/services/logs-container.service';
 
 import {LogsContainerComponent} from './logs-container.component';
 
@@ -59,7 +61,8 @@ describe('LogsContainerComponent', () => {
           auditLogsFields,
           serviceLogs,
           serviceLogsFields,
-          serviceLogsHistogramData
+          serviceLogsHistogramData,
+          hosts
         })
       ],
       providers: [
@@ -76,8 +79,10 @@ describe('LogsContainerComponent', () => {
         ServiceLogsService,
         ServiceLogsFieldsService,
         ServiceLogsHistogramDataService,
+        HostsService,
         FilteringService,
-        UtilsService
+        UtilsService,
+        LogsContainerService
       ],
       schemas: [CUSTOM_ELEMENTS_SCHEMA]
     })

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/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 517db98..3e2a6c7 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
@@ -20,12 +20,8 @@ import {Component, OnInit, Input} from '@angular/core';
 import {FormGroup} from '@angular/forms';
 import {Observable} from 'rxjs/Observable';
 import 'rxjs/add/operator/map';
-import {HttpClientService} from '@app/services/http-client.service';
 import {FilteringService} from '@app/services/filtering.service';
-import {AuditLogsService} from '@app/services/storage/audit-logs.service';
-import {AuditLogsFieldsService} from 
'@app/services/storage/audit-logs-fields.service';
-import {ServiceLogsService} from '@app/services/storage/service-logs.service';
-import {ServiceLogsFieldsService} from 
'@app/services/storage/service-logs-fields.service';
+import {LogsContainerService} from '@app/services/logs-container.service';
 import {ServiceLogsHistogramDataService} from 
'@app/services/storage/service-logs-histogram-data.service';
 import {AppStateService} from '@app/services/storage/app-state.service';
 import {AuditLog} from '@app/models/audit-log.model';
@@ -39,33 +35,28 @@ 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) {
-    serviceLogsHistogramStorage.getAll().subscribe(data => {
-      let histogramData = {};
-      data.forEach(type => {
-        const name = type.name;
-        type.dataCount.forEach(entry => {
-          const timeStamp = new Date(entry.name).valueOf();
-          if (!histogramData[timeStamp]) {
-            let initialValue = {};
-            Object.keys(this.histogramOptions.keysWithColors).forEach(key => 
initialValue[key] = 0);
-            histogramData[timeStamp] = initialValue;
-          }
-          histogramData[timeStamp][name] = Number(entry.value);
-        });
-      });
-      this.histogramData = histogramData;
-    });
+  constructor(private serviceLogsHistogramStorage: 
ServiceLogsHistogramDataService, private appState: AppStateService, private 
filtering: FilteringService, private logsContainer: LogsContainerService) {
+    serviceLogsHistogramStorage.getAll().subscribe(data => this.histogramData 
= this.logsContainer.getHistogramData(data));
   }
 
   ngOnInit() {
-    this.logsTypeMapObject = this.logsTypeMap[this.logsType];
+    const fieldsModel = this.logsTypeMapObject.fieldsModel,
+      logsModel = this.logsTypeMapObject.logsModel;
     
this.appState.getParameter(this.logsTypeMapObject.isSetFlag).subscribe(value => 
this.isLogsSet = value);
-    this.availableColumns = 
this[this.logsTypeMapObject.fieldsModel].getAll().map(fields => {
-      const availableFields = fields.filter(field => field.isAvailable),
+    this.availableColumns = fieldsModel.getAll().map(fields => {
+      return fields.filter(field => field.isAvailable).map(field => {
+        return {
+          value: field.name,
+          label: field.displayName || field.name,
+          isChecked: field.isDisplayed
+        };
+      });
+    });
+    fieldsModel.getAll().subscribe(columns => {
+      const availableFields = columns.filter(field => field.isAvailable),
         availableNames = availableFields.map(field => field.name);
       if (availableNames.length && !this.isLogsSet) {
-        this.logs = this[this.logsTypeMapObject.logsModel].getAll().map(logs 
=> logs.map(log => {
+        this.logs = logsModel.getAll().map(logs => logs.map(log => {
           let logObject = availableNames.reduce((obj, key) => 
Object.assign(obj, {
             [key]: log[key]
           }), {});
@@ -76,63 +67,24 @@ export class LogsContainerComponent implements OnInit {
         }));
         this.appState.setParameter(this.logsTypeMapObject.isSetFlag, true);
       }
-      return availableFields.map(field => {
-        return {
-          value: field.name,
-          label: field.displayName || field.name,
-          isChecked: field.isDisplayed
-        };
-      });
-    });
-    this[this.logsTypeMapObject.fieldsModel].getAll().subscribe(columns => {
       this.displayedColumns = columns.filter(column => column.isAvailable && 
column.isDisplayed);
     });
-    this.loadLogs();
-    this.filtersForm.valueChanges.subscribe(() => {
-      this.loadLogs();
-    });
+    this.logsContainer.loadLogs(this.logsType);
+    this.filtersForm.valueChanges.subscribe(() => 
this.logsContainer.loadLogs(this.logsType));
   }
 
   @Input()
-  private logsType: string;
+  logsType: string;
 
   private isLogsSet: boolean = false;
 
-  logsTypeMapObject: any;
-
-  totalCount: number = 0;
-
-  private readonly listFilters = {
-    clusters: ['clusters'],
-    text: ['iMessage'],
-    timeRange: ['end_time', 'start_time'],
-    components: ['mustBe'],
-    levels: ['level'],
-    sorting: ['sortType', 'sortBy'],
-    pageSize: ['pageSize'],
-    page: ['page']
-  };
-
-  private readonly histogramFilters = {
-    clusters: ['clusters'],
-    text: ['iMessage'],
-    timeRange: ['to', 'from'],
-    components: ['mustBe'],
-    levels: ['level']
-  };
+  get logsTypeMapObject(): any {
+    return this.logsContainer.logsTypeMap[this.logsType];
+  }
 
-  private readonly logsTypeMap = {
-    auditLogs: {
-      logsModel: 'auditLogsStorage',
-      fieldsModel: 'auditLogsFieldsStorage',
-      isSetFlag: 'isAuditLogsSet'
-    },
-    serviceLogs: {
-      logsModel: 'serviceLogsStorage',
-      fieldsModel: 'serviceLogsFieldsStorage',
-      isSetFlag: 'isServiceLogsSet'
-    }
-  };
+  get totalCount(): number {
+    return this.logsContainer.totalCount;
+  }
 
   logs: Observable<AuditLog[] | ServiceLog[]>;
 
@@ -143,71 +95,11 @@ export class LogsContainerComponent implements OnInit {
   histogramData: any;
 
   readonly histogramOptions = {
-    keysWithColors: {
-      WARN: '#FF8916',
-      ERROR: '#E81D1D',
-      FATAL: '#830A0A',
-      INFO: '#2577B5',
-      DEBUG: '#65E8FF',
-      TRACE: '#888',
-      UNKNOWN: '#BDBDBD'
-    }
+    keysWithColors: this.logsContainer.colors
   };
 
   private get filtersForm(): FormGroup {
     return this.filtering.filtersForm;
   }
 
-  private loadLogs(): void {
-    this.httpClient.get(this.logsType, 
this.getParams('listFilters')).subscribe(response => {
-      const jsonResponse = response.json();
-      this.serviceLogsStorage.clear();
-      if (jsonResponse) {
-        const logs = jsonResponse.logList,
-          count = jsonResponse.totalCount || 0;
-        if (logs) {
-          this.serviceLogsStorage.addInstances(logs);
-        }
-        this.totalCount = count;
-      }
-    });
-    this.httpClient.get('serviceLogsHistogram', 
this.getParams('histogramFilters')).subscribe(response => {
-      const jsonResponse = response.json();
-      this.serviceLogsHistogramStorage.clear();
-      if (jsonResponse) {
-        const histogramData = jsonResponse.graphData;
-        if (histogramData) {
-          this.serviceLogsHistogramStorage.addInstances(histogramData);
-        }
-      }
-    });
-  }
-
-  private getParams(filtersMapName: string): any {
-    let params = {};
-    Object.keys(this[filtersMapName]).forEach(key => {
-      const inputValue = this.filtersForm.getRawValue()[key],
-        paramNames = this[filtersMapName][key];
-      paramNames.forEach(paramName => {
-        let value;
-        const valueGetter = this.filtering.valueGetters[paramName];
-        if (valueGetter) {
-          if (paramName === 'start_time') {
-            value = valueGetter(inputValue, params['end_time']);
-          } else if (paramName === 'from') {
-            value = valueGetter(inputValue, params['to']);
-          } else {
-            value = valueGetter(inputValue);
-          }
-        } else {
-          value = inputValue;
-        }
-        if (value != null && value !== '') {
-          params[paramName] = value;
-        }
-      });
-    }, this);
-    return params;
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
index 23a62a4..888c524 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
@@ -17,7 +17,7 @@
 
 <form *ngIf="logs && logs.length" [formGroup]="filtersForm" class="pull-right">
   <filter-dropdown [label]="filters.sorting.label" formControlName="sorting" 
[options]="filters.sorting.options"
-                   [defaultLabel]="filters.sorting.defaultLabel" 
isRightAlign="true"></filter-dropdown>
+                   [defaultLabel]="filters.sorting.defaultLabel" 
[isRightAlign]="true"></filter-dropdown>
 </form>
 <div class="col-md-12 text-center" *ngIf="logs && logs.length">
   <div class="logs-header">

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
index 96adc8f..02c3b23 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
@@ -28,6 +28,7 @@ import {ServiceLogsService, serviceLogs} from 
'@app/services/storage/service-log
 import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 import {ClustersService, clusters} from 
'@app/services/storage/clusters.service';
 import {ComponentsService, components} from 
'@app/services/storage/components.service';
+import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {HttpClientService} from '@app/services/http-client.service';
 import {FilteringService} from '@app/services/filtering.service';
 import {UtilsService} from '@app/services/utils.service';
@@ -59,7 +60,8 @@ describe('LogsListComponent', () => {
           serviceLogs,
           appSettings,
           clusters,
-          components
+          components,
+          hosts
         }),
         MomentModule,
         MomentTimezoneModule,
@@ -79,6 +81,7 @@ describe('LogsListComponent', () => {
         AppSettingsService,
         ClustersService,
         ComponentsService,
+        HostsService,
         FilteringService,
         UtilsService
       ],

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
index a0f25ff..2f05656 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
@@ -23,5 +23,6 @@
   <a *ngIf="label" (mousedown)="onMouseDown($event)" [ngClass]="labelClass" 
(mouseup)="onMouseUp($event)"
      (click)="$event.stopPropagation()">{{label | translate}}</a>
   <ul data-component="dropdown-list" *ngIf="hasSubItems" [items]="subItems" 
(selectedItemChange)="updateValue($event)"
-      [isMultipleChoice]="isMultipleChoice" [ngClass]="{'dropdown-menu': true, 
'dropdown-menu-right': isRightAlign}"></ul>
+      [isMultipleChoice]="isMultipleChoice" 
[additionalLabelComponentSetter]="additionalLabelComponentSetter"
+      [ngClass]="{'dropdown-menu': true, 'dropdown-menu-right': 
isRightAlign}"></ul>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
index 0b58ce1..b674ec6 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
@@ -49,13 +49,16 @@ export class MenuButtonComponent {
   subItems?: any[];
 
   @Input()
-  isMultipleChoice?: boolean = false;
+  isMultipleChoice: boolean = false;
 
   @Input()
-  hideCaret?: boolean = false;
+  hideCaret: boolean = false;
 
   @Input()
-  isRightAlign?: boolean = false;
+  isRightAlign: boolean = false;
+
+  @Input()
+  additionalLabelComponentSetter?: string;
 
   get hasSubItems(): boolean {
     return Boolean(this.subItems && this.subItems.length);

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.html
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.html
new file mode 100644
index 0000000..96c8619
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.html
@@ -0,0 +1,19 @@
+<!--
+  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 *ngFor="let item of data" class="bar-sector"
+     [ngStyle]="{'background-color': item.color, 'width': (item.value / 
totalCount * 100) + '%'}"></div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.less
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.less
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.less
new file mode 100644
index 0000000..b78b847
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.less
@@ -0,0 +1,39 @@
+/**
+ * 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.
+ */
+
+@bar-height: 8px;
+
+:host {
+  display: block;
+  width: 100%;
+
+  .bar-sector {
+    display: inline-block;
+    height: @bar-height;
+
+    &:first-child {
+      border-top-left-radius: @bar-height / 2;
+      border-bottom-left-radius: @bar-height / 2;
+    }
+
+    &:last-child {
+      border-top-right-radius: @bar-height / 2;
+      border-bottom-right-radius: @bar-height / 2;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.spec.ts
new file mode 100644
index 0000000..d47436e
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.spec.ts
@@ -0,0 +1,43 @@
+/**
+ * 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 {NodeBarComponent} from './node-bar.component';
+
+describe('NodeBarComponent', () => {
+  let component: NodeBarComponent;
+  let fixture: ComponentFixture<NodeBarComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [NodeBarComponent]
+    })
+      .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(NodeBarComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create component', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.ts
new file mode 100644
index 0000000..c7b3ead
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/node-bar/node-bar.component.ts
@@ -0,0 +1,35 @@
+/**
+ * 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';
+
+@Component({
+  selector: 'node-bar',
+  templateUrl: './node-bar.component.html',
+  styleUrls: ['./node-bar.component.less']
+})
+export class NodeBarComponent {
+
+  @Input()
+  data: any[] = [];
+
+  get totalCount(): number {
+    return this.data.reduce((currentValue, currentItem) => currentValue + 
Number(currentItem.value), 0);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.html
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.html
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.html
index 67fe591..be6591b 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.html
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/pagination/pagination.component.html
@@ -17,7 +17,7 @@
 
 <form class="pagination-form col-md-12" [formGroup]="filtersForm">
   <filter-dropdown [label]="filterInstance.label" formControlName="pageSize" 
[options]="filterInstance.options"
-                   [defaultLabel]="filterInstance.defaultLabel" 
isRightAlign="true" isDropup="true"></filter-dropdown>
+                   [defaultLabel]="filterInstance.defaultLabel" 
[isRightAlign]="true" isDropup="true"></filter-dropdown>
   <span>{{'pagination.numbers' | translate: numbersTranslateParams}}</span>
   <pagination-controls formControlName="page" [totalCount]="totalCount" 
[pagesCount]="pagesCount"
                        
(currentPageChange)="setCurrentPage($event)"></pagination-controls>

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/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 3404a4b..f23139b 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
@@ -662,6 +662,14 @@ export const mockData = {
             ]
           },
           hosts: {
+            groupList: [
+              {
+                host: 'h0'
+              },
+              {
+                host: 'h1'
+              }
+            ],
             components: {
               vNodeList: [
                 {
@@ -790,70 +798,127 @@ export const mockData = {
           tree: {
             vNodeList: [
               {
-                name: 'ambari',
-                type: 0,
-                logLevelCount: [
+                name: 'h0',
+                type: 'H',
+                value: '1',
+                childs: [
                   {
-                    name: 'ERROR',
-                    value: '1000'
-                  },
+                    name: 'ams_collector',
+                    type: 'C',
+                    value: '1',
+                    logLevelCount: [
+                      {
+                        name: 'WARN',
+                        value: '1'
+                      }
+                    ],
+                    isParent: false,
+                    isRoot: false
+                  }
+                ],
+                logLevelCount: [
                   {
                     name: 'WARN',
-                    value: '5000'
+                    value: '1'
                   }
                 ],
+                isParent: true,
+                isRoot: true
+              },
+              {
+                name: 'h1',
+                type: 'H',
+                value: '6',
                 childs: [
                   {
-                    name: 'yarn',
-                    type: 2,
+                    name: 'ams_collector',
+                    type: 'C',
+                    value: '1',
                     logLevelCount: [
                       {
                         name: 'ERROR',
-                        value: '1000'
+                        value: '1'
+                      }
+                    ],
+                    isParent: false,
+                    isRoot: false
+                  },
+                  {
+                    name: 'ambari_agent',
+                    type: 'C',
+                    value: '1',
+                    logLevelCount: [
+                      {
+                        name: 'FATAL',
+                        value: '1'
+                      }
+                    ],
+                    isParent: false,
+                    isRoot: false
+                  },
+                  {
+                    name: 'zookeeper_server',
+                    type: 'C',
+                    value: '2',
+                    logLevelCount: [
+                      {
+                        name: 'INFO',
+                        value: '1'
                       },
                       {
-                        name: 'WARN',
-                        value: '2000'
+                        name: 'DEBUG',
+                        value: '1'
                       }
                     ],
                     isParent: false,
                     isRoot: false
                   },
                   {
-                    name: 'hive',
-                    type: 3,
+                    name: 'zookeeper_client',
+                    type: 'C',
+                    value: '2',
                     logLevelCount: [
                       {
-                        name: 'ERROR',
-                        value: '2000'
+                        name: 'TRACE',
+                        value: '1'
                       },
                       {
-                        name: 'WARN',
-                        value: '4000'
+                        name: 'UNKNOWN',
+                        value: '1'
                       }
                     ],
                     isParent: false,
                     isRoot: false
                   }
                 ],
-                isParent: true,
-                isRoot: false
-              },
-              {
-                name: 'ambari_server',
-                type: 1,
                 logLevelCount: [
                   {
                     name: 'ERROR',
-                    value: '10000'
+                    value: '1'
                   },
                   {
-                    name: 'WARN',
-                    value: '50000'
+                    name: 'FATAL',
+                    value: '1'
+                  },
+                  {
+                    name: 'INFO',
+                    value: '1'
+                  },
+                  {
+                    name: 'DEBUG',
+                    value: '1'
+                  },
+                  {
+                    name: 'TRACE',
+                    value: '1'
+                  },
+                  {
+                    name: 'UNKNOWN',
+                    value: '1'
                   }
                 ],
-                isParent: false,
-                isRoot: false
+                isParent: true,
+                isRoot: true
               }
             ]
           },

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/models/node.model.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/models/node.model.ts 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/node.model.ts
index a89c4fb..2891d142 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/models/node.model.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/node.model.ts
@@ -20,7 +20,7 @@ import {CommonEntry} from '@app/models/common-entry.model';
 
 export interface Node {
   name: string;
-  type?: number;
+  type?: string;
   value: string;
   isParent: boolean;
   isRoot: boolean;

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts
index 8d71174..31d52b3 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts
@@ -47,7 +47,7 @@ export interface AppStore {
   serviceLogs: ServiceLog[];
   serviceLogsHistogramData: BarGraph[];
   graphs: Graph[];
-  nodes: Node[];
+  hosts: Node[];
   userConfigs: UserConfig[];
   filters: Filter[];
   clusters: string[];

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/component-generator.service.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/component-generator.service.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/component-generator.service.spec.ts
new file mode 100644
index 0000000..b6ec8d7
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/component-generator.service.spec.ts
@@ -0,0 +1,84 @@
+/**
+ * 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, inject} from '@angular/core/testing';
+import {StoreModule} from '@ngrx/store';
+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 {ServiceLogsFieldsService, serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
+import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from 
'@app/services/storage/service-logs-histogram-data.service';
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
+import {ClustersService, clusters} from 
'@app/services/storage/clusters.service';
+import {ComponentsService, components} from 
'@app/services/storage/components.service';
+import {LogsContainerService} from '@app/services/logs-container.service';
+import {HttpClientService} from '@app/services/http-client.service';
+import {FilteringService} from '@app/services/filtering.service';
+
+import {ComponentGeneratorService} from './component-generator.service';
+
+describe('ComponentGeneratorService', () => {
+  beforeEach(() => {
+    const httpClient = {
+      get: () => {
+        return {
+          subscribe: () => {
+          }
+        }
+      }
+    };
+    TestBed.configureTestingModule({
+      imports: [
+        StoreModule.provideStore({
+          hosts,
+          auditLogs,
+          serviceLogs,
+          auditLogsFields,
+          serviceLogsFields,
+          serviceLogsHistogramData,
+          appSettings,
+          clusters,
+          components
+        })
+      ],
+      providers: [
+        ComponentGeneratorService,
+        LogsContainerService,
+        {
+          provide: HttpClientService,
+          useValue: httpClient
+        },
+        FilteringService,
+        HostsService,
+        AuditLogsService,
+        ServiceLogsService,
+        AuditLogsFieldsService,
+        ServiceLogsFieldsService,
+        ServiceLogsHistogramDataService,
+        AppSettingsService,
+        ClustersService,
+        ComponentsService
+      ]
+    });
+  });
+
+  it('should create service', inject([ComponentGeneratorService], (service: 
ComponentGeneratorService) => {
+    expect(service).toBeTruthy();
+  }));
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/component-generator.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/component-generator.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/component-generator.service.ts
new file mode 100644
index 0000000..c49f40f
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/component-generator.service.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 {Injectable, ComponentFactoryResolver, ViewContainerRef} from 
'@angular/core';
+import {HostsService} from '@app/services/storage/hosts.service';
+import {LogsContainerService} from '@app/services/logs-container.service';
+import {NodeBarComponent} from '@app/components/node-bar/node-bar.component';
+
+@Injectable()
+export class ComponentGeneratorService {
+
+  constructor(private resolver: ComponentFactoryResolver, private 
hostsStorage: HostsService, private logsContainer: LogsContainerService) {
+  }
+
+  private createComponent(type: any, container: ViewContainerRef, properties?: 
any): void {
+    const factory = this.resolver.resolveComponentFactory(type);
+    container.clear();
+    let component = container.createComponent(factory);
+    Object.assign(component.instance, properties);
+  }
+
+  getDataForHostsNodeBar(hostName: string, container: ViewContainerRef): void {
+    let data;
+    this.hostsStorage.getAll().subscribe(hosts => {
+      if (container && hosts && hosts.length) {
+        const selectedHost = hosts.find(host => host.name === hostName);
+        data = selectedHost.logLevelCount.map(event => {
+          return {
+            color: this.logsContainer.colors[event.name],
+            value: event.value
+          };
+        });
+        if (data.length) {
+          this.createComponent(NodeBarComponent, container, {
+            data
+          });
+        }
+      }
+    });
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
index 4be15b4..e3f731e 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
@@ -21,18 +21,29 @@ import {StoreModule} from '@ngrx/store';
 import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
 import {ClustersService, clusters} from 
'@app/services/storage/clusters.service';
 import {ComponentsService, components} from 
'@app/services/storage/components.service';
+import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {UtilsService} from '@app/services/utils.service';
+import {HttpClientService} from '@app/services/http-client.service';
 
 import {FilteringService} from './filtering.service';
 
 describe('FilteringService', () => {
   beforeEach(() => {
+    const httpClient = {
+      get: () => {
+        return {
+          subscribe: () => {
+          }
+        }
+      }
+    };
     TestBed.configureTestingModule({
       imports: [
         StoreModule.provideStore({
           appSettings,
           clusters,
-          components
+          components,
+          hosts
         })
       ],
       providers: [
@@ -40,7 +51,12 @@ describe('FilteringService', () => {
         AppSettingsService,
         ClustersService,
         ComponentsService,
-        UtilsService
+        HostsService,
+        UtilsService,
+        {
+          provide: HttpClientService,
+          useValue: httpClient
+        }
       ]
     });
   });

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/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 8088872..5b9e90d 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,11 +22,13 @@ 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 {HostsService} from '@app/services/storage/hosts.service';
+import {HttpClientService} from '@app/services/http-client.service';
 
 @Injectable()
 export class FilteringService {
 
-  constructor(private appSettings: AppSettingsService, private 
clustersStorage: ClustersService, private componentsStorage: ComponentsService) 
{
+  constructor(private httpClient: HttpClientService, private appSettings: 
AppSettingsService, private clustersStorage: ClustersService, private 
componentsStorage: ComponentsService, private hostsStorage: HostsService) {
     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)];
@@ -34,6 +36,14 @@ export class FilteringService {
     componentsStorage.getAll().subscribe(components => {
       this.filters.components.options = [...this.filters.components.options, 
...components.map(this.getListItem)];
     });
+    hostsStorage.getAll().subscribe(hosts => {
+      this.filters.hosts.options = [...this.filters.hosts.options, 
...hosts.map(host => {
+        return {
+          label: `${host.name} (${host.value})`,
+          value: host.name
+        };
+      })];
+    });
   }
 
   private getListItem(name: string): any {
@@ -176,6 +186,12 @@ export class FilteringService {
       ],
       defaultValue: ''
     },
+    hosts: {
+      label: 'filter.hosts',
+      iconClass: 'fa fa-server',
+      options: [],
+      defaultValue: ''
+    },
     sorting: {
       label: 'sorting.title',
       options: [
@@ -252,6 +268,36 @@ export class FilteringService {
 
   filtersForm = new FormGroup(this.filtersFormItems);
 
+  loadClusters(): void {
+    this.httpClient.get('clusters').subscribe(response => {
+      const clusterNames = response.json();
+      if (clusterNames) {
+        this.clustersStorage.addInstances(clusterNames);
+      }
+    });
+  }
+
+  loadComponents(): void {
+    this.httpClient.get('components').subscribe(response => {
+      const jsonResponse = response.json(),
+        components = jsonResponse && jsonResponse.groupList;
+      if (components) {
+        const componentNames = components.map(component => component.type);
+        this.componentsStorage.addInstances(componentNames);
+      }
+    });
+  }
+
+  loadHosts(): void {
+    this.httpClient.get('hosts').subscribe(response => {
+      const jsonResponse = response.json(),
+        hosts = jsonResponse && jsonResponse.vNodeList;
+      if (hosts) {
+        this.hostsStorage.addInstances(hosts);
+      }
+    });
+  }
+
   private getStartTime(value: any, current: string): string {
     let time;
     if (value) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts
index 625a55c..8fed570 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts
@@ -61,6 +61,9 @@ export class HttpClientService extends Http {
     },
     clusters: {
       url: 'service/logs/clusters'
+    },
+    hosts: {
+      url: 'service/logs/tree'
     }
   };
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/logs-container.service.spec.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/logs-container.service.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/logs-container.service.spec.ts
new file mode 100644
index 0000000..8ebbd72
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/logs-container.service.spec.ts
@@ -0,0 +1,82 @@
+/**
+ * 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, inject} from '@angular/core/testing';
+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 {ServiceLogsFieldsService, serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
+import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from 
'@app/services/storage/service-logs-histogram-data.service';
+import {AppSettingsService, appSettings} from 
'@app/services/storage/app-settings.service';
+import {ClustersService, clusters} from 
'@app/services/storage/clusters.service';
+import {ComponentsService, components} from 
'@app/services/storage/components.service';
+import {HostsService, hosts} from '@app/services/storage/hosts.service';
+import {HttpClientService} from '@app/services/http-client.service';
+import {FilteringService} from '@app/services/filtering.service';
+
+import {LogsContainerService} from './logs-container.service';
+
+describe('LogsContainerService', () => {
+  beforeEach(() => {
+    const httpClient = {
+      get: () => {
+        return {
+          subscribe: () => {
+          }
+        }
+      }
+    };
+    TestBed.configureTestingModule({
+      imports: [
+        StoreModule.provideStore({
+          auditLogs,
+          serviceLogs,
+          auditLogsFields,
+          serviceLogsFields,
+          serviceLogsHistogramData,
+          appSettings,
+          clusters,
+          components,
+          hosts
+        })
+      ],
+      providers: [
+        AuditLogsService,
+        ServiceLogsService,
+        AuditLogsFieldsService,
+        ServiceLogsFieldsService,
+        ServiceLogsHistogramDataService,
+        AppSettingsService,
+        ClustersService,
+        ComponentsService,
+        HostsService,
+        LogsContainerService,
+        {
+          provide: HttpClientService,
+          useValue: httpClient
+        },
+        FilteringService
+      ]
+    });
+  });
+
+  it('should create service', inject([LogsContainerService], (service: 
LogsContainerService) => {
+    expect(service).toBeTruthy();
+  }));
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/logs-container.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/logs-container.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/logs-container.service.ts
new file mode 100644
index 0000000..702deab
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/logs-container.service.ts
@@ -0,0 +1,148 @@
+/**
+ * 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 {HttpClientService} from '@app/services/http-client.service';
+import {FilteringService} from '@app/services/filtering.service';
+import {AuditLogsService} from '@app/services/storage/audit-logs.service';
+import {AuditLogsFieldsService} from 
'@app/services/storage/audit-logs-fields.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';
+
+@Injectable()
+export class LogsContainerService {
+
+  constructor(private httpClient: HttpClientService, private auditLogsStorage: 
AuditLogsService, private auditLogsFieldsStorage: AuditLogsFieldsService, 
private serviceLogsStorage: ServiceLogsService, private 
serviceLogsFieldsStorage: ServiceLogsFieldsService, private 
serviceLogsHistogramStorage: ServiceLogsHistogramDataService, private 
filtering: FilteringService) {
+  }
+
+  readonly colors = {
+    WARN: '#FF8916',
+    ERROR: '#E81D1D',
+    FATAL: '#830A0A',
+    INFO: '#2577B5',
+    DEBUG: '#65E8FF',
+    TRACE: '#888',
+    UNKNOWN: '#BDBDBD'
+  };
+
+  private readonly listFilters = {
+    clusters: ['clusters'],
+    text: ['iMessage'],
+    timeRange: ['end_time', 'start_time'],
+    components: ['mustBe'],
+    levels: ['level'],
+    hosts: ['host_name'],
+    sorting: ['sortType', 'sortBy'],
+    pageSize: ['pageSize'],
+    page: ['page']
+  };
+
+  private readonly histogramFilters = {
+    clusters: ['clusters'],
+    text: ['iMessage'],
+    timeRange: ['to', 'from'],
+    components: ['mustBe'],
+    levels: ['level']
+  };
+
+  readonly logsTypeMap = {
+    auditLogs: {
+      logsModel: this.auditLogsStorage,
+      fieldsModel: this.auditLogsFieldsStorage,
+      isSetFlag: 'isAuditLogsSet'
+    },
+    serviceLogs: {
+      logsModel: this.serviceLogsStorage,
+      fieldsModel: this.serviceLogsFieldsStorage,
+      isSetFlag: 'isServiceLogsSet'
+    }
+  };
+
+  totalCount: number = 0;
+
+  loadLogs(logsType: string): void {
+    this.httpClient.get(logsType, 
this.getParams('listFilters')).subscribe(response => {
+      const jsonResponse = response.json();
+      this.logsTypeMap[logsType].logsModel.clear();
+      if (jsonResponse) {
+        const logs = jsonResponse.logList,
+          count = jsonResponse.totalCount || 0;
+        if (logs) {
+          this.serviceLogsStorage.addInstances(logs);
+        }
+        this.totalCount = count;
+      }
+    });
+    this.httpClient.get('serviceLogsHistogram', 
this.getParams('histogramFilters')).subscribe(response => {
+      const jsonResponse = response.json();
+      this.serviceLogsHistogramStorage.clear();
+      if (jsonResponse) {
+        const histogramData = jsonResponse.graphData;
+        if (histogramData) {
+          this.serviceLogsHistogramStorage.addInstances(histogramData);
+        }
+      }
+    });
+  }
+
+  private getParams(filtersMapName: string): any {
+    let params = {};
+    Object.keys(this[filtersMapName]).forEach(key => {
+      const inputValue = this.filtering.filtersForm.getRawValue()[key],
+        paramNames = this[filtersMapName][key];
+      paramNames.forEach(paramName => {
+        let value;
+        const valueGetter = this.filtering.valueGetters[paramName];
+        if (valueGetter) {
+          if (paramName === 'start_time') {
+            value = valueGetter(inputValue, params['end_time']);
+          } else if (paramName === 'from') {
+            value = valueGetter(inputValue, params['to']);
+          } else {
+            value = valueGetter(inputValue);
+          }
+        } else {
+          value = inputValue;
+        }
+        if (value != null && value !== '') {
+          params[paramName] = value;
+        }
+      });
+    }, this);
+    return params;
+  }
+
+  getHistogramData(data: any[]): any {
+    let histogramData = {};
+    data.forEach(type => {
+      const name = type.name;
+      type.dataCount.forEach(entry => {
+        const timeStamp = new Date(entry.name).valueOf();
+        if (!histogramData[timeStamp]) {
+          let initialValue = {};
+          Object.keys(this.colors).forEach(key => initialValue[key] = 0);
+          histogramData[timeStamp] = initialValue;
+        }
+        histogramData[timeStamp][name] = Number(entry.value);
+      });
+    });
+    return histogramData;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts
index 2289f09..ec89d9f 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts
@@ -59,6 +59,10 @@ export class mockApiDataService implements InMemoryDbService 
{
         end_time: {
           key: 'logtime',
           filterFunction: (value, filterValue) => value < 
moment(filterValue).valueOf()
+        },
+        host_name: {
+          key: 'host',
+          isValuesList: true
         }
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/hosts.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/hosts.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/hosts.service.ts
new file mode 100644
index 0000000..0cb0a74
--- /dev/null
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/hosts.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/models/store.model';
+
+export const modelName = 'hosts';
+
+@Injectable()
+export class HostsService extends CollectionModelService {
+  constructor(store: Store<AppStore>) {
+    super(modelName, store);
+  }
+}
+
+export const hosts = getCollectionReducer(modelName);

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/nodes.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/nodes.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/nodes.service.ts
deleted file mode 100644
index 83ec551..0000000
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/nodes.service.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * 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/models/store.model';
-
-export const modelName = 'nodes';
-
-@Injectable()
-export class NodesService extends CollectionModelService {
-  constructor(store: Store<AppStore>) {
-    super(modelName, store);
-  }
-}
-
-export const nodes = getCollectionReducer(modelName);

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts
----------------------------------------------------------------------
diff --git 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts
 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts
index d941beb..08f237d 100644
--- 
a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts
@@ -24,7 +24,7 @@ import {clusters} from 
'@app/services/storage/clusters.service';
 import {components} from '@app/services/storage/components.service';
 import {filters} from '@app/services/storage/filters.service';
 import {graphs} from '@app/services/storage/graphs.service';
-import {nodes} from '@app/services/storage/nodes.service';
+import {hosts} from '@app/services/storage/hosts.service';
 import {serviceLogs} from '@app/services/storage/service-logs.service';
 import {serviceLogsHistogramData} from 
'@app/services/storage/service-logs-histogram-data.service';
 import {serviceLogsFields} from 
'@app/services/storage/service-logs-fields.service';
@@ -38,7 +38,7 @@ export const reducers = {
   serviceLogs,
   serviceLogsHistogramData,
   graphs,
-  nodes,
+  hosts,
   userConfigs,
   filters,
   clusters,

http://git-wip-us.apache.org/repos/asf/ambari/blob/5f1b9858/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 5c7ab8d..84c4abc 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
@@ -22,6 +22,7 @@
   "filter.levels": "Levels",
   "filter.capture": "Capture",
   "filter.excluded": "Excluded",
+  "filter.hosts": "Hosts",
 
   "filter.timeRange.1hr": "Last 1 hour",
   "filter.timeRange.24hr": "Last 24 hours",

Reply via email to