You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ab...@apache.org on 2017/11/30 18:36:43 UTC

ambari git commit: AMBARI-22564 Log Search UI: layout and behaviour changes for filtering. (ababiichuk)

Repository: ambari
Updated Branches:
  refs/heads/trunk 1a803ccab -> 63a15872f


AMBARI-22564 Log Search UI: layout and behaviour changes for filtering. (ababiichuk)


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

Branch: refs/heads/trunk
Commit: 63a15872fec4ffec793878258b13b356e74528fa
Parents: 1a803cc
Author: ababiichuk <ab...@hortonworks.com>
Authored: Thu Nov 30 18:03:18 2017 +0200
Committer: ababiichuk <ab...@hortonworks.com>
Committed: Thu Nov 30 20:39:06 2017 +0200

----------------------------------------------------------------------
 .../action-menu/action-menu.component.less      |  3 -
 .../action-menu/action-menu.component.ts        |  4 --
 .../audit-logs-table.component.html             |  8 ++-
 .../dropdown-button.component.html              |  4 +-
 .../dropdown-button.component.less              | 17 +++---
 .../dropdown-button.component.ts                |  3 +
 .../filters-panel/filters-panel.component.html  | 14 ++---
 .../filters-panel/filters-panel.component.less  | 11 +++-
 .../filters-panel/filters-panel.component.ts    | 21 +++++--
 .../menu-button/menu-button.component.less      | 13 +---
 .../src/app/components/mixins.less              | 17 ++++++
 .../pagination/pagination.component.html        |  4 +-
 .../search-box/search-box.component.html        |  2 +-
 .../search-box/search-box.component.less        | 18 +++---
 .../search-box/search-box.component.ts          | 38 ++++++++----
 .../service-logs-table.component.html           |  7 ++-
 .../service-logs-table.component.less           |  1 -
 .../components/top-menu/top-menu.component.html |  7 ++-
 .../components/top-menu/top-menu.component.less |  4 ++
 .../top-menu/top-menu.component.spec.ts         | 64 +++++++++++++++++++-
 .../components/top-menu/top-menu.component.ts   | 25 +++++++-
 .../src/app/components/variables.less           |  3 +-
 .../src/app/services/logs-container.service.ts  | 11 +++-
 .../src/assets/i18n/en.json                     |  2 +-
 .../ambari-logsearch-web/webpack.config.js      | 20 +++---
 25 files changed, 225 insertions(+), 96 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.less
index 880a97b..fff57df 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.less
@@ -15,13 +15,10 @@
  * limitations under the License.
  */
 
-@import '../variables';
-
 :host {
   display: block;
   margin-left: auto;
   menu-button {
     margin: 0 1em;
-    color: @table-border-color;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.ts
index 58e0025..72037f8 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/action-menu/action-menu.component.ts
@@ -30,7 +30,6 @@ export class ActionMenuComponent {
     {
       iconClass: 'fa fa-arrow-left',
       label: 'topMenu.undo',
-      labelClass: 'unstyled-link',
       action: 'undo',
       subItems: [
         {
@@ -50,7 +49,6 @@ export class ActionMenuComponent {
     {
       iconClass: 'fa fa-arrow-right',
       label: 'topMenu.redo',
-      labelClass: 'unstyled-link',
       action: 'redo',
       subItems: [
         {
@@ -67,13 +65,11 @@ export class ActionMenuComponent {
     {
       iconClass: 'fa fa-refresh',
       label: 'topMenu.refresh',
-      labelClass: 'unstyled-link',
       action: 'refresh'
     },
     {
       iconClass: 'fa fa-history',
       label: 'topMenu.history',
-      labelClass: 'unstyled-link',
       action: 'openHistory',
       isRightAlign: true,
       subItems: [

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.html
index d6e9091..cad09bc 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.html
@@ -15,12 +15,14 @@
   limitations under the License.
 -->
 
-<dropdown-button class="pull-right" label="logs.columns" [options]="columns" [isRightAlign]="true"
+<dropdown-button class="pull-right" label="{{'logs.columns' | translate}}" [options]="columns" [isRightAlign]="true"
                  [isMultipleChoice]="true" action="updateSelectedColumns"
                  [additionalArgs]="logsTypeMapObject.fieldsModel"></dropdown-button>
 <form *ngIf="logs && logs.length" [formGroup]="filtersForm" class="row pull-right">
-  <filter-dropdown class="col-md-12" [label]="filters.auditLogsSorting.label" formControlName="auditLogsSorting"
-                   [options]="filters.auditLogsSorting.options" [isRightAlign]="true"></filter-dropdown></form>
+  <filter-dropdown class="col-md-12" label="{{filters.auditLogsSorting.label | translate}}"
+                   formControlName="auditLogsSorting" [options]="filters.auditLogsSorting.options"
+                   [isRightAlign]="true"></filter-dropdown>
+</form>
 <div class="panel panel-default">
   <div class="panel-body">
     <table class="table">

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.html
index b5f1e56..d047d7a 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.html
@@ -16,11 +16,11 @@
 -->
 
 <div [ngClass]="{'dropup': isDropup}">
-  <button class="btn btn-link dropdown-toggle" data-toggle="dropdown">
+  <button [ngClass]="['btn', 'btn-link', 'dropdown-toggle', buttonClass]" data-toggle="dropdown">
     <span *ngIf="iconClass || label"
           [ngClass]="{'filter-label': true, 'plain': !isMultipleChoice && !hideCaret && showSelectedValue}">
       <span *ngIf="iconClass" [ngClass]="iconClass"></span>
-      <span *ngIf="label">{{label | translate}}</span>
+      <span *ngIf="label">{{label}}</span>
     </span>
     <span *ngIf="showSelectedValue && !isMultipleChoice && selection.length">{{selection[0].label | translate}}</span>
     <span *ngIf="!hideCaret" class="caret"></span>

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less
index d767e15..7b560c1 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less
@@ -20,17 +20,16 @@
 :host {
   .default-flex;
   position: relative;
-  float: left;
 
-  .filter-label {
-    padding: @input-group-addon-padding;
+  button {
+    text-transform: none;
 
-    &.plain {
-      color: initial;
-    }
-  }
+    .filter-label {
+      padding: @input-group-addon-padding;
 
-  .btn {
-    text-transform: none;
+      &.plain {
+        color: initial;
+      }
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.ts
index 148e1b4..a8037d0 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.ts
@@ -35,6 +35,9 @@ export class DropdownButtonComponent {
   label?: string;
 
   @Input()
+  buttonClass: string = '';
+
+  @Input()
   iconClass?: string;
 
   @Input()

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html
index 4fe169d..440efde 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html
@@ -17,22 +17,20 @@
 
 <form [formGroup]="filtersForm">
   <div class="form-inline filter-input-container col-md-8">
-    <filter-dropdown *ngIf="isFilterConditionDisplayed('clusters')" [label]="filters.clusters.label"
-                     formControlName="clusters" [options]="filters.clusters.options" [isMultipleChoice]="true"
-                     class="filter-input"></filter-dropdown>
     <search-box [parameterAddSubject]="queryParameterAdd" [parameterNameChangeSubject]="queryParameterNameChange"
                 formControlName="query" [items]="searchBoxItemsTranslated" [itemsOptions]="options"
-                class="filter-input"></search-box>
+                [updateValueImmediately]="false" [updateValueSubject]="searchBoxValueUpdate" class="filter-input"></search-box>
     <time-range-picker *ngIf="isFilterConditionDisplayed('timeRange')" formControlName="timeRange"
                        class="filter-input"></time-range-picker>
     <timezone-picker class="filter-input"></timezone-picker>
-    <!--button class="btn btn-success" type="button">
+    <button class="btn btn-success search-button" type="button" (click)="updateSearchBoxValue()">
       <span class="fa fa-search"></span>
-    </button-->
+    </button>
   </div>
   <div class="filter-buttons col-md-4">
-    <dropdown-button [options]="searchBoxItems | async" iconClass="fa fa-search-minus" label="filter.excluded"
-                     [hideCaret]="true" [showSelectedValue]="false" action="proceedWithExclude"></dropdown-button>
+    <dropdown-button [options]="searchBoxItems | async" iconClass="fa fa-search-minus" action="proceedWithExclude"
+                     label="{{'filter.exclude' | translate}}" [hideCaret]="true"
+                     [showSelectedValue]="false"></dropdown-button>
     <filter-button *ngIf="isFilterConditionDisplayed('hosts')" formControlName="hosts"
                    label="{{filters.hosts.label | translate}}" [iconClass]="filters.hosts.iconClass"
                    [subItems]="filters.hosts.options" [isMultipleChoice]="true" [isRightAlign]="true"

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less
index 962199b..e2f9a1e 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less
@@ -28,9 +28,14 @@
     align-items: flex-start;
     justify-content: flex-start;
 
-    .btn-success {
-      border-top-left-radius: 0;
-      border-bottom-left-radius: 0;
+    .search-button {
+      border: 1px solid @submit-color;
+      height: auto;
+
+      &:last-child {
+        border-top-left-radius: 0;
+        border-bottom-left-radius: 0;
+      }
     }
 
     .filter-input {

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
index 01a8932..1717bd7 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
@@ -20,7 +20,8 @@ import {Component, OnChanges, SimpleChanges, Input} from '@angular/core';
 import {FormGroup} from '@angular/forms';
 import {Observable} from 'rxjs/Observable';
 import {Subject} from 'rxjs/Subject';
-import {FilterCondition} from '@app/classes/filtering';
+import 'rxjs/add/observable/from';
+import {FilterCondition, SearchBoxParameter, SearchBoxParameterTriggered} from '@app/classes/filtering';
 import {ListItem} from '@app/classes/list-item';
 import {LogsType} from '@app/classes/string';
 import {CommonEntry} from '@app/classes/models/common-entry';
@@ -46,6 +47,9 @@ export class FiltersPanelComponent implements OnChanges {
         case 'serviceLogs':
           result = this.logsContainer.serviceLogsColumns;
           break;
+        default:
+          result = Observable.from([]);
+          break;
       }
       this.searchBoxItems = result;
     }
@@ -65,6 +69,8 @@ export class FiltersPanelComponent implements OnChanges {
         return this.logsContainer.auditLogsColumnsTranslated;
       case 'serviceLogs':
         return this.logsContainer.serviceLogsColumnsTranslated;
+      default:
+        return [];
     }
   }
 
@@ -93,11 +99,11 @@ export class FiltersPanelComponent implements OnChanges {
     }, {});
   }
 
-  get queryParameterNameChange(): Subject<any> {
+  get queryParameterNameChange(): Subject<SearchBoxParameterTriggered> {
     return this.logsContainer.queryParameterNameChange;
   }
 
-  get queryParameterAdd(): Subject<any> {
+  get queryParameterAdd(): Subject<SearchBoxParameter> {
     return this.logsContainer.queryParameterAdd;
   }
 
@@ -105,9 +111,14 @@ export class FiltersPanelComponent implements OnChanges {
     return this.logsContainer.captureSeconds;
   }
 
+  searchBoxValueUpdate: Subject<void> = new Subject();
+
   isFilterConditionDisplayed(key: string): boolean {
-    return this.logsContainer.logsTypeMap[this.logsType].listFilters.indexOf(key) > -1
-      && Boolean(this.filtersForm.controls[key]);
+    return this.logsContainer.isFilterConditionDisplayed(key);
+  }
+
+  updateSearchBoxValue(): void {
+    this.searchBoxValueUpdate.next();
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less
index 0207561..0ec3dd0 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-@import '../variables';
+@import '../mixins';
 
 :host {
   cursor: pointer;
@@ -24,8 +24,7 @@
   a {
     text-align: center;
     text-decoration: none;
-    i {
-      color: @link-color;
+    .icon {
       display: inline-block;
       position: relative;
       &.fa-caret-down {
@@ -36,14 +35,6 @@
       display: block;
     }
   }
-  a:hover, a:focus {
-    i {
-      color: @link-hover-color;
-    }
-  }
-  .unstyled-link {
-    color: inherit;
-  }
 
   .badge {
     background: @badge-bg;

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less
index 4460821..0bf169d 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less
@@ -140,6 +140,23 @@
   }
 }
 
+.grey {
+  color: @grey-color;
+}
+
+.collapsed-form-control {
+  width: 0;
+  padding: 0;
+}
+
+.inherited-color {
+  color: inherit;
+
+  &:hover {
+    color: inherit;
+  }
+}
+
 /**
  * Caret mixin definition.
  * The .caret mixin has two parameters: the width of the caret and the direction of the caret

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.html
index 4be0a47..02ed84b 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.html
@@ -16,8 +16,8 @@
 -->
 
 <form class="pagination-form" [formGroup]="filtersForm">
-  <filter-dropdown [label]="filterInstance.label" formControlName="pageSize" [options]="filterInstance.options"
-                   [isRightAlign]="true" [isDropup]="true"></filter-dropdown>
+  <filter-dropdown label="{{filterInstance.label | translate}}" formControlName="pageSize"
+                   [options]="filterInstance.options" [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/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html
index 5bffdc5..5ab9a69 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html
@@ -30,7 +30,7 @@
            (valueChanged)="changeParameterName({value: $event.value, isExclude: false})"
            (keyup)="onParameterKeyUp($event)">
   </span>
-  <span [ngClass]="{'no-value-options': !activeItemValueOptions.length}">
+  <span [ngClass]="{'no-options': !activeItemValueOptions.length}">
     <input #valueInput auto-complete [(ngModel)]="currentValue" [source]="activeItemValueOptions"
            [list-formatter]="itemsListFormatter" [value-formatter]="itemsValueFormatter" [match-formatted]="true"
            (valueChanged)="onParameterValueChange($event.value)" (keydown)="onParameterValueKeyDown($event)"

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less
index eac3bd6..9deea92 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less
@@ -20,10 +20,6 @@
 
 @inactive-input-width: 1px;
 @label-margin: 2px;
-.collapsed-form-control {
-  width: 0;
-  padding: 0;
-}
 
 :host {
   display: flex;
@@ -38,7 +34,7 @@
     margin: @label-margin;
     border-radius: @dropdown-border-radius;
     padding: @search-parameter-padding;
-    background-color: @search-parameter-background-color;
+    background-color: @grey-color;
     color: @base-font-color;
     font-size: 0.8em;
 
@@ -97,16 +93,16 @@
           }
         }
 
-        .no-value-options {
-          /deep/ .ng2-auto-complete {
-            display: none;
-          }
-        }
-
         .value-input {
           width: 100%;
         }
       }
+
+      .no-options {
+        /deep/ .ng2-auto-complete {
+          display: none;
+        }
+      }
     }
 
     /deep/ .ng2-auto-complete {

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts
index 14cc89b..64b8c36 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts
@@ -51,6 +51,7 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
     this.valueInput.addEventListener('blur', this.onValueInputBlur);
     this.parameterNameChangeSubject.subscribe(this.onParameterNameChange);
     this.parameterAddSubject.subscribe(this.onParameterAdd);
+    this.updateValueSubject.subscribe(this.updateValue);
   }
 
   ngOnDestroy(): void {
@@ -61,6 +62,7 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
     this.valueInput.removeEventListener('blur', this.onValueInputBlur);
     this.parameterNameChangeSubject.unsubscribe();
     this.parameterAddSubject.unsubscribe();
+    this.updateValueSubject.unsubscribe();
   }
 
   private readonly messageParameterName: string = 'log_message';
@@ -69,8 +71,6 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
 
   private isExclude: boolean = false;
 
-  private defaultSubject: Subject<any> = new Subject();
-
   isActive: boolean = false;
 
   isParameterInput: boolean = false;
@@ -86,10 +86,20 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
   itemsOptions: {[key: string]: CommonEntry[]};
 
   @Input()
-  parameterNameChangeSubject: Subject<SearchBoxParameterTriggered> = this.defaultSubject;
+  parameterNameChangeSubject: Subject<SearchBoxParameterTriggered> = new Subject();
+
+  @Input()
+  parameterAddSubject: Subject<SearchBoxParameter> = new Subject();
+
+  @Input()
+  updateValueSubject: Subject<void> = new Subject();
 
+  /**
+   * Indicates whether form should receive updated value immediately after user adds new search parameter
+   * @type {boolean}
+   */
   @Input()
-  parameterAddSubject: Subject<SearchBoxParameter> = this.defaultSubject;
+  updateValueImmediately: boolean = true;
 
   @ViewChild('parameterInput')
   parameterInputRef: ElementRef;
@@ -147,7 +157,7 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
   private switchToParameterInput = (): void => {
     this.activeItem = null;
     this.isValueInput = false;
-    setTimeout(() => this.parameterInput.focus());
+    setTimeout(() => this.parameterInput.focus(), 0);
   };
 
   private getItemByValue(name: string): CommonEntry {
@@ -211,7 +221,9 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
         value: value,
         isExclude: this.isExclude
       });
-      this.updateValue();
+      if (this.updateValueImmediately) {
+        this.updateValueSubject.next();
+      }
     }
     this.switchToParameterInput();
   }
@@ -225,7 +237,9 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
       value: options.value,
       isExclude: options.isExclude
     });
-    this.updateValue();
+    if (this.updateValueImmediately) {
+      this.updateValueSubject.next();
+    }
   };
 
   onParameterKeyUp = (event: KeyboardEvent): void => {
@@ -248,20 +262,22 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
 
   removeParameter(event: MouseEvent, id: number): void {
     this.parameters = this.parameters.filter((parameter: SearchBoxParameterProcessed): boolean => parameter.id !== id);
-    this.updateValue();
+    if (this.updateValueImmediately) {
+      this.updateValueSubject.next();
+    }
     event.stopPropagation();
   }
 
-  updateValue(): void {
+  updateValue = (): void => {
     this.currentValue = '';
     if (this.onChange) {
       this.onChange(this.parameters);
     }
-  }
+  };
 
   writeValue(parameters: SearchBoxParameterProcessed[] = []): void {
     this.parameters = parameters;
-    this.updateValue();
+    this.updateValueSubject.next();
   }
 
   registerOnChange(callback: any): void {

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.html
index a2e666e..7f9c6d7 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.html
@@ -15,12 +15,13 @@
   limitations under the License.
 -->
 
-<dropdown-button class="pull-right" label="logs.columns" [options]="columns" [isRightAlign]="true"
+<dropdown-button class="pull-right" label="{{'logs.columns' | translate}}" [options]="columns" [isRightAlign]="true"
                  [isMultipleChoice]="true" action="updateSelectedColumns"
                  [additionalArgs]="logsTypeMapObject.fieldsModel"></dropdown-button>
 <form *ngIf="logs && logs.length" [formGroup]="filtersForm" class="row pull-right">
-  <filter-dropdown class="col-md-12" [label]="filters.serviceLogsSorting.label" formControlName="serviceLogsSorting"
-                   [options]="filters.serviceLogsSorting.options" [isRightAlign]="true"></filter-dropdown>
+  <filter-dropdown class="col-md-12" label="{{filters.serviceLogsSorting.label | translate}}"
+                   formControlName="serviceLogsSorting" [options]="filters.serviceLogsSorting.options"
+                   [isRightAlign]="true"></filter-dropdown>
 </form>
 <div class="panel panel-default">
   <div class="panel-body">

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.less
index bd6d012..dfa1889 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.less
@@ -53,7 +53,6 @@
       }
     }
     &.log-time {
-      color: @grey-color;
       min-width: 7em;
       text-align: right;
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html
index 369ddd4..910e55f 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html
@@ -16,8 +16,13 @@
 -->
 
 <div class="pull-right">
+  <form [formGroup]="filtersForm" class="filters">
+    <filter-dropdown *ngIf="isClustersFilterDisplayed" formControlName="clusters" [options]="filters.clusters.options"
+                     [isMultipleChoice]="true" label="{{filters.clusters.label | translate}}" [isRightAlign]="true"
+                     buttonClass="inherited-color"></filter-dropdown>
+  </form>
   <menu-button *ngFor="let item of items" label="{{item.label | translate}}" [action]="item.action"
                [iconClass]="item.iconClass" [labelClass]="item.labelClass" [subItems]="item.subItems"
-               [hideCaret]="item.hideCaret" [badge]="item.badge"  [isRightAlign]="item.isRightAlign">
+               [hideCaret]="item.hideCaret" [badge]="item.badge" [isRightAlign]="item.isRightAlign">
   </menu-button>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less
index 32d1beb..257768c 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less
@@ -20,4 +20,8 @@
 :host {
   .default-flex;
   margin-right: 0;
+
+  .filters {
+    display: inline-block;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/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 6679ba1..ba5b613 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
@@ -18,18 +18,80 @@
 
 import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
 import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+import {ReactiveFormsModule} from '@angular/forms';
+import {StoreModule} from '@ngrx/store';
 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 {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.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 {AppStateService, appState} from '@app/services/storage/app-state.service';
+import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
+import {TabsService, tabs} from '@app/services/storage/tabs.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 {LogsContainerService} from '@app/services/logs-container.service';
+import {HttpClientService} from '@app/services/http-client.service';
 
 import {TopMenuComponent} from './top-menu.component';
 
 describe('TopMenuComponent', () => {
   let component: TopMenuComponent;
   let fixture: ComponentFixture<TopMenuComponent>;
+  const httpClient = {
+    get: () => {
+      return {
+        subscribe: () => {
+        }
+      };
+    }
+  };
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      imports: TranslationModules,
+      imports: [
+        ReactiveFormsModule,
+        StoreModule.provideStore({
+          auditLogs,
+          serviceLogs,
+          auditLogsFields,
+          serviceLogsFields,
+          serviceLogsHistogramData,
+          serviceLogsTruncated,
+          appState,
+          appSettings,
+          tabs,
+          clusters,
+          components,
+          hosts
+        }),
+        ...TranslationModules
+      ],
       declarations: [TopMenuComponent],
+      providers: [
+        LogsContainerService,
+        {
+          provide: HttpClientService,
+          useValue: httpClient
+        },
+        AuditLogsService,
+        ServiceLogsService,
+        AuditLogsFieldsService,
+        ServiceLogsFieldsService,
+        ServiceLogsHistogramDataService,
+        ServiceLogsTruncatedService,
+        AppStateService,
+        AppSettingsService,
+        TabsService,
+        ClustersService,
+        ComponentsService,
+        HostsService
+      ],
       schemas: [CUSTOM_ELEMENTS_SCHEMA]
     })
     .compileComponents();

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.ts
index 91f27e8..6df7ab3 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.ts
@@ -17,6 +17,10 @@
  */
 
 import {Component} from '@angular/core';
+import {FormGroup} from '@angular/forms';
+import {FilterCondition, TimeUnitListItem} from '@app/classes/filtering';
+import {ListItem} from '@app/classes/list-item';
+import {LogsContainerService} from '@app/services/logs-container.service';
 
 @Component({
   selector: 'top-menu',
@@ -25,10 +29,21 @@ import {Component} from '@angular/core';
 })
 export class TopMenuComponent {
 
+  constructor(private logsContainer: LogsContainerService) {
+  }
+
+  get filtersForm(): FormGroup {
+    return this.logsContainer.filtersForm;
+  };
+
+  get filters(): {[key: string]: FilterCondition} {
+    return this.logsContainer.filters;
+  };
+
   //TODO implement loading of real data into subItems
   readonly items = [
     {
-      iconClass: 'fa fa-user unstyled-link',
+      iconClass: 'fa fa-user grey',
       hideCaret: true,
       isRightAlign: true,
       subItems: [
@@ -43,4 +58,12 @@ export class TopMenuComponent {
     }
   ];
 
+  get clusters(): (ListItem | TimeUnitListItem[])[] {
+    return this.filters.clusters.options;
+  }
+
+  get isClustersFilterDisplayed(): boolean {
+    return this.logsContainer.isFilterConditionDisplayed('clusters') && this.clusters.length > 1;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less
index 18268ad..a9ca3b4 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less
@@ -27,7 +27,7 @@
 @block-margin-top: 20px;
 @link-color: #1491C1;
 @link-hover-color: #23527C;
-@grey-color: #666;
+@grey-color: #DDD;
 @default-line-height: 1.42857143;
 @main-background-color: #ECECEC;
 @filters-panel-background-color: #FFF;
@@ -52,7 +52,6 @@
 @submit-color: #5CB85C;
 @submit-hover-color: #449D44;
 @exclude-color: #EF6162;
-@search-parameter-background-color: #DDD;
 
 // Panels
 @panel-heading: rgba(255, 255, 255, 1);

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/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 64b14b8..4adf577 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
@@ -546,7 +546,7 @@ export class LogsContainerService {
 
   activeLogsType: LogsType;
 
-  private filtersFormChange: Subject<any> = new Subject();
+  private filtersFormChange: Subject<void> = new Subject();
 
   private columnsMapper<FieldT extends LogField>(fields: FieldT[]): ListItem[] {
     return fields.filter((field: FieldT): boolean => field.isAvailable).map((field: FieldT): ListItem => {
@@ -628,9 +628,9 @@ export class LogsContainerService {
 
   queryParameterAdd: Subject<SearchBoxParameter> = new Subject();
 
-  private stopTimer: Subject<any> = new Subject();
+  private stopTimer: Subject<void> = new Subject();
 
-  private stopAutoRefreshCountdown: Subject<any> = new Subject();
+  private stopAutoRefreshCountdown: Subject<void> = new Subject();
 
   captureSeconds: number = 0;
 
@@ -962,4 +962,9 @@ export class LogsContainerService {
     }, {});
   }
 
+  isFilterConditionDisplayed(key: string): boolean {
+    return this.logsTypeMap[this.activeLogsType].listFilters.indexOf(key) > -1
+      && Boolean(this.filtersForm.controls[key]);
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/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 98b9e29..6c916aa 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json
+++ b/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json
@@ -26,7 +26,7 @@
   "filter.clusters": "Clusters",
   "filter.components": "Components",
   "filter.levels": "Levels",
-  "filter.excluded": "Excluded",
+  "filter.exclude": "Exclude",
   "filter.hosts": "Hosts",
 
   "filter.capture": "Capture",

http://git-wip-us.apache.org/repos/asf/ambari/blob/63a15872/ambari-logsearch/ambari-logsearch-web/webpack.config.js
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/webpack.config.js b/ambari-logsearch/ambari-logsearch-web/webpack.config.js
index 75d6aee..e1a2366 100644
--- a/ambari-logsearch/ambari-logsearch-web/webpack.config.js
+++ b/ambari-logsearch/ambari-logsearch-web/webpack.config.js
@@ -102,11 +102,11 @@ module.exports = {
       "./src/polyfills.ts"
     ],
     "styles": [
-      "./src/styles.less",
       "./node_modules/bootstrap/dist/css/bootstrap.min.css",
       "./node_modules/font-awesome/css/font-awesome.min.css",
       "./src/vendor/css/bootstrap-logsearch.min.css",
-      "./src/vendor/css/bootstrap-datetimepicker.min.css"
+      "./src/vendor/css/bootstrap-datetimepicker.min.css",
+      "./src/styles.less"
     ]
   },
   "output": {
@@ -271,11 +271,11 @@ module.exports = {
       },
       {
         "include": [
-          path.join(process.cwd(), "src/styles.less"),
           path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
           path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
           path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css"),
-          path.join(process.cwd(), "src/vendor/css/bootstrap-datetimepicker.min.css")
+          path.join(process.cwd(), "src/vendor/css/bootstrap-datetimepicker.min.css"),
+          path.join(process.cwd(), "src/styles.less")
         ],
         "test": /\.css$/,
         "use": [
@@ -298,11 +298,11 @@ module.exports = {
       },
       {
         "include": [
-          path.join(process.cwd(), "src/styles.less"),
           path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
           path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
           path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css"),
-          path.join(process.cwd(), "src/vendor/css/bootstrap-datetimepicker.min.css")
+          path.join(process.cwd(), "src/vendor/css/bootstrap-datetimepicker.min.css"),
+          path.join(process.cwd(), "src/styles.less")
         ],
         "test": /\.scss$|\.sass$/,
         "use": [
@@ -333,11 +333,11 @@ module.exports = {
       },
       {
         "include": [
-          path.join(process.cwd(), "src/styles.less"),
           path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
           path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
           path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css"),
-          path.join(process.cwd(), "src/vendor/css/bootstrap-datetimepicker.min.css")
+          path.join(process.cwd(), "src/vendor/css/bootstrap-datetimepicker.min.css"),
+          path.join(process.cwd(), "src/styles.less")
         ],
         "test": /\.less$/,
         "use": [
@@ -367,11 +367,11 @@ module.exports = {
       },
       {
         "include": [
-          path.join(process.cwd(), "src/styles.less"),
           path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
           path.join(process.cwd(), "node_modules/font-awesome/css/font-awesome.min.css"),
           path.join(process.cwd(), "src/vendor/css/bootstrap-logsearch.min.css"),
-          path.join(process.cwd(), "src/vendor/css/bootstrap-datetimepicker.min.css")
+          path.join(process.cwd(), "src/vendor/css/bootstrap-datetimepicker.min.css"),
+          path.join(process.cwd(), "src/styles.less")
         ],
         "test": /\.styl$/,
         "use": [