ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akuznet...@apache.org
Subject ignite git commit: IGNITE-4774 Redesign table.
Date Wed, 26 Apr 2017 11:40:35 GMT
Repository: ignite
Updated Branches:
  refs/heads/ignite-2.0 335f24317 -> c829aacaf


IGNITE-4774 Redesign table.


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

Branch: refs/heads/ignite-2.0
Commit: c829aacaf71b06b32be3345c3c70047230b9f9e5
Parents: 335f243
Author: Dmitriy Shabalin <dmitriyff@gmail.com>
Authored: Wed Apr 26 18:41:32 2017 +0700
Committer: Alexey Kuznetsov <akuznetsov@apache.org>
Committed: Wed Apr 26 18:41:32 2017 +0700

----------------------------------------------------------------------
 .../list-of-registered-users.column-defs.js     |  26 +-
 .../list-of-registered-users.controller.js      | 163 +++++-----
 .../list-of-registered-users.tpl.pug            |  25 +-
 .../frontend/app/primitives/badge/index.scss    |   1 +
 .../frontend/app/primitives/btn/index.scss      |  24 +-
 .../frontend/app/primitives/dropdown/index.pug  |   2 +-
 .../frontend/app/primitives/dropdown/index.scss |  26 +-
 .../frontend/app/primitives/panel/index.scss    |   2 +-
 .../app/primitives/ui-grid-header/index.scss    |  10 +-
 .../app/primitives/ui-grid-header/index.tpl.pug |  10 +-
 .../app/primitives/ui-grid-settings/index.scss  |  58 +++-
 .../frontend/app/primitives/ui-grid/index.scss  | 149 +++++++--
 .../frontend/gulpfile.babel.js/paths.js         |   1 +
 .../frontend/gulpfile.babel.js/tasks/bundle.js  |   2 +-
 .../webpack/environments/development.js         |   4 +-
 .../frontend/public/images/icons/cross.svg      |   1 +
 .../frontend/public/images/icons/export.svg     |   1 +
 .../frontend/public/images/icons/gear.svg       |   1 +
 .../stylesheets/_bootstrap-variables.scss       |   4 +-
 modules/web-console/licenses/cc-by-3.0.txt      | 319 +++++++++++++++++++
 20 files changed, 669 insertions(+), 160 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js
index 5bacce4..cb95735 100644
--- a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js
+++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js
@@ -50,11 +50,11 @@ const EMAIL_TEMPLATE = '<div class="ui-grid-cell-contents"><a ng-href="mailto:{{
 
 export default [
     {name: 'actions', displayName: 'Actions', categoryDisplayName: 'Actions', cellTemplate: ACTIONS_TEMPLATE, field: 'actions', minWidth: 70, width: 70, enableFiltering: false, enableSorting: false, visible: false},
-    {name: 'user', displayName: 'User', categoryDisplayName: 'User', field: 'userName', cellTemplate: USER_TEMPLATE, minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by name...' }},
+    {name: 'user', displayName: 'User', categoryDisplayName: 'User', field: 'userName', cellTemplate: USER_TEMPLATE, minWidth: 160, enableFiltering: true, pinnedLeft: true, filter: { placeholder: 'Filter by name...' }},
     {name: 'email', displayName: 'Email', categoryDisplayName: 'Email', field: 'email', cellTemplate: EMAIL_TEMPLATE, minWidth: 160, enableFiltering: false, filter: { placeholder: 'Filter by email...' }},
-    {name: 'company', displayName: 'Company', categoryDisplayName: 'Company', field: 'company', minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by company...' }},
-    {name: 'country', displayName: 'Country', categoryDisplayName: 'Country', field: 'countryCode', minWidth: 120, enableFiltering: true, filter: { placeholder: 'Filter by country...' }},
-    {name: 'lastlogin', displayName: 'Last login', categoryDisplayName: 'Last login', field: 'lastLogin', cellFilter: 'date:"M/d/yy HH:mm"', minWidth: 105, width: 105, enableFiltering: false, visible: false},
+    {name: 'company', displayName: 'Company', categoryDisplayName: 'Company', field: 'company', minWidth: 180, enableFiltering: true, filter: { placeholder: 'Filter by company...' }},
+    {name: 'country', displayName: 'Country', categoryDisplayName: 'Country', field: 'countryCode', minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by country...' }},
+    {name: 'lastlogin', displayName: 'Last login', categoryDisplayName: 'Last login', field: 'lastLogin', cellFilter: 'date:"M/d/yy HH:mm"', minWidth: 120, width: 120, enableFiltering: false, visible: false},
     {name: 'lastactivity', displayName: 'Last activity', categoryDisplayName: 'Last activity', field: 'lastActivity', cellFilter: 'date:"M/d/yy HH:mm"', minWidth: 130, width: 130, enableFiltering: false, visible: true, sort: { direction: 'desc', priority: 0 }},
     // Configurations
     {name: 'cfg_clusters', displayName: 'Clusters count', categoryDisplayName: 'Configurations', headerCellTemplate: CLUSTER_HEADER_TEMPLATE, field: 'counters.clusters', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Clusters count', minWidth: 65, width: 65, enableFiltering: false, visible: false},
@@ -66,15 +66,15 @@ export default [
     {name: 'qry', displayName: 'Qry', categoryDisplayName: 'Total activities', field: 'activitiesTotal["queries"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Total count of queries usages', minWidth: 70, width: 70, enableFiltering: false},
     {name: 'demo', displayName: 'Demo', categoryDisplayName: 'Total activities', field: 'activitiesTotal["demo"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Total count of demo startup', minWidth: 85, width: 85, enableFiltering: false},
     {name: 'dnld', displayName: 'Dnld', categoryDisplayName: 'Total activities', field: 'activitiesDetail["/agent/download"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Total count of agent downloads', minWidth: 80, width: 80, enableFiltering: false},
-    {name: 'starts', displayName: 'Starts', categoryDisplayName: 'Total activities', field: 'activitiesDetail["/agent/start"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Total count of agent startup', minWidth: 80, width: 80, enableFiltering: false},
+    {name: 'starts', displayName: 'Starts', categoryDisplayName: 'Total activities', field: 'activitiesDetail["/agent/start"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Total count of agent startup', minWidth: 87, width: 87, enableFiltering: false},
     // Activities Configuration
-    {name: 'clusters', displayName: 'Clusters', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/clusters"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration clusters', minWidth: 80, width: 80, enableFiltering: false, visible: false},
-    {name: 'model', displayName: 'Model', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/domains"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration model', minWidth: 80, width: 80, enableFiltering: false, visible: false},
-    {name: 'caches', displayName: 'Caches', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/caches"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration caches', minWidth: 80, width: 80, enableFiltering: false, visible: false},
-    {name: 'igfs', displayName: 'IGFS', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/igfs"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration IGFS', minWidth: 80, width: 80, enableFiltering: false, visible: false},
-    {name: 'summary', displayName: 'Summary', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/summary"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration summary', minWidth: 80, width: 80, enableFiltering: false, visible: false},
+    {name: 'clusters', displayName: 'Clusters', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/clusters"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration clusters', minWidth: 100, width: 100, enableFiltering: false, visible: false},
+    {name: 'model', displayName: 'Model', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/domains"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration model', minWidth: 87, width: 87, enableFiltering: false, visible: false},
+    {name: 'caches', displayName: 'Caches', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/caches"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration caches', minWidth: 96, width: 96, enableFiltering: false, visible: false},
+    {name: 'igfs', displayName: 'IGFS', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/igfs"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration IGFS', minWidth: 85, width: 85, enableFiltering: false, visible: false},
+    {name: 'summary', displayName: 'Summary', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/summary"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Configuration summary', minWidth: 111, width: 111, enableFiltering: false, visible: false},
     // Activities Queries
-    {name: 'execute', displayName: 'Execute', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/execute"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Query executions', minWidth: 65, width: 80, enableFiltering: false, visible: false},
-    {name: 'explain', displayName: 'Explain', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/explain"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Query explain executions', minWidth: 65, width: 80, enableFiltering: false, visible: false},
-    {name: 'scan', displayName: 'Scan', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/scan"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Scan query executions', minWidth: 65, width: 80, enableFiltering: false, visible: false}
+    {name: 'execute', displayName: 'Execute', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/execute"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Query executions', minWidth: 98, width: 98, enableFiltering: false, visible: false},
+    {name: 'explain', displayName: 'Explain', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/explain"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Query explain executions', minWidth: 95, width: 95, enableFiltering: false, visible: false},
+    {name: 'scan', displayName: 'Scan', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/scan"] || 0', type: 'number', cellClass: 'ui-grid-number-cell', headerTooltip: 'Scan query executions', minWidth: 80, width: 80, enableFiltering: false, visible: false}
 ];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.controller.js b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.controller.js
index 0fc1cd6..0faa561 100644
--- a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.controller.js
+++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.controller.js
@@ -28,10 +28,14 @@ const rowTemplate = `<div
   role="{{col.isRowHeader ? 'rowheader' : 'gridcell'}}"
   ui-grid-cell/>`;
 
+const treeAggregationFinalizerFn = function(agg) {
+    return agg.rendered = agg.value;
+};
+
 export default class IgniteListOfRegisteredUsersCtrl {
-    static $inject = ['$scope', '$state', '$filter', 'User', 'uiGridGroupingConstants', 'IgniteAdminData', 'IgniteNotebookData', 'IgniteConfirm', 'IgniteActivitiesUserDialog'];
+    static $inject = ['$scope', '$state', '$filter', 'User', 'uiGridGroupingConstants', 'uiGridPinningConstants', 'IgniteAdminData', 'IgniteNotebookData', 'IgniteConfirm', 'IgniteActivitiesUserDialog'];
 
-    constructor($scope, $state, $filter, User, uiGridGroupingConstants, AdminData, NotebookData, Confirm, ActivitiesUserDialog) {
+    constructor($scope, $state, $filter, User, uiGridGroupingConstants, uiGridPinningConstants, AdminData, NotebookData, Confirm, ActivitiesUserDialog) {
         const $ctrl = this;
 
         const dtFilter = $filter('date');
@@ -45,6 +49,7 @@ export default class IgniteListOfRegisteredUsersCtrl {
             endDate: new Date()
         };
 
+        $ctrl.uiGridPinningConstants = uiGridPinningConstants;
         $ctrl.uiGridGroupingConstants = uiGridGroupingConstants;
 
         User.read().then((user) => $ctrl.user = user);
@@ -142,12 +147,12 @@ export default class IgniteListOfRegisteredUsersCtrl {
             columnDefs,
             categories,
 
+            treeRowHeaderAlwaysVisible: true,
             headerTemplate,
             columnVirtualizationThreshold: 30,
             rowTemplate,
             rowHeight: 46,
             selectWithCheckboxOnly: true,
-            selectionRowHeaderWidth: 52,
             suppressRemoveSort: false,
             enableFiltering: true,
             enableSelectAll: true,
@@ -293,118 +298,118 @@ export default class IgniteListOfRegisteredUsersCtrl {
         this.groupBy = 'user';
 
         this.gridApi.grouping.clearGrouping();
-        this.gridOptions.categories = this._userGridOptions.categories;
-        this.gridOptions.columnDefs = this._userGridOptions.columnDefs;
+        this.gridApi.selection.clearSelectedRows();
+
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'company'}), (col) => {
+            this.gridApi.pinning.pinColumn(col, this.uiGridPinningConstants.container.NONE);
+        });
+
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'country'}), (col) => {
+            this.gridApi.pinning.pinColumn(col, this.uiGridPinningConstants.container.NONE);
+        });
+
+        this.gridOptions.categories = categories;
     }
 
     groupByCompany() {
         this.groupBy = 'company';
 
         this.gridApi.grouping.clearGrouping();
+        this.gridApi.selection.clearSelectedRows();
+
+        _.forEach(this.gridApi.grid.columns, (col) => {
+            col.enableSorting = true;
+
+            if (col.colDef.type !== 'number')
+                return;
+
+            this.gridApi.grouping.aggregateColumn(col.colDef.name, this.uiGridGroupingConstants.aggregation.SUM);
+            col.customTreeAggregationFinalizerFn = treeAggregationFinalizerFn;
+        });
 
-        this.gridApi.grouping.groupColumn('company');
         this.gridApi.grouping.aggregateColumn('user', this.uiGridGroupingConstants.aggregation.COUNT);
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'user'}), (col) => {
+            col.customTreeAggregationFinalizerFn = treeAggregationFinalizerFn;
+        });
 
-        if (this._companyGridOptions) {
-            this.gridOptions.categories = this._companyGridOptions.categories;
-            this.gridOptions.columnDefs = this._companyGridOptions.columnDefs;
+        this.gridApi.grouping.aggregateColumn('lastactivity', this.uiGridGroupingConstants.aggregation.MAX);
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'lastactivity'}), (col) => {
+            col.customTreeAggregationFinalizerFn = treeAggregationFinalizerFn;
+        });
 
-            return;
-        }
+        this.gridApi.grouping.groupColumn('company');
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'company'}), (col) => {
+            col.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.groupVal;
+        });
 
-        const _categories = _.cloneDeep(categories);
-        const _columnDefs = _.cloneDeep(columnDefs);
+        // Pinning left company.
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'company'}), (col) => {
+            this.gridApi.pinning.pinColumn(col, this.uiGridPinningConstants.container.LEFT);
+        });
 
+        // Unpinning country.
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'country'}), (col) => {
+            this.gridApi.pinning.pinColumn(col, this.uiGridPinningConstants.container.NONE);
+        });
+
+        const _categories = _.cloneDeep(categories);
         // Cut company category.
         const company = _categories.splice(3, 1)[0];
         company.selectable = false;
 
-        // Hide Actions category.
-        _categories.splice(0, 1);
-
-        _.forEach(_.filter(_columnDefs, {displayName: 'Actions'}), (col) => {
-            col.visible = false;
-        });
-
         // Add company as first column.
         _categories.unshift(company);
+        this.gridOptions.categories = _categories;
+    }
+
+    groupByCountry() {
+        this.groupBy = 'country';
+
+        this.gridApi.grouping.clearGrouping();
+        this.gridApi.selection.clearSelectedRows();
 
-        _.forEach(_columnDefs, (col) => {
+        _.forEach(this.gridApi.grid.columns, (col) => {
             col.enableSorting = true;
 
-            if (col.type !== 'number')
+            if (col.colDef.type !== 'number')
                 return;
 
-            col.treeAggregationType = this.uiGridGroupingConstants.aggregation.SUM;
-            col.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.value;
+            this.gridApi.grouping.aggregateColumn(col.colDef.name, this.uiGridGroupingConstants.aggregation.SUM);
+            col.customTreeAggregationFinalizerFn = treeAggregationFinalizerFn;
         });
 
-        // Set grouping to last activity column.
-        const lastactivity = _.find(_columnDefs, { name: 'lastactivity' });
-
-        if (_.nonNil(lastactivity)) {
-            lastactivity.treeAggregationType = this.uiGridGroupingConstants.aggregation.MAX;
-            lastactivity.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.value;
-        }
-
-        this._companyGridOptions = {
-            categories: this.gridOptions.categories = _categories,
-            columnDefs: this.gridOptions.columnDefs = _columnDefs
-        };
-    }
+        this.gridApi.grouping.aggregateColumn('user', this.uiGridGroupingConstants.aggregation.COUNT);
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'user'}), (col) => {
+            col.customTreeAggregationFinalizerFn = treeAggregationFinalizerFn;
+        });
 
-    groupByCountry() {
-        this.groupBy = 'country';
+        this.gridApi.grouping.aggregateColumn('lastactivity', this.uiGridGroupingConstants.aggregation.MAX);
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'lastactivity'}), (col) => {
+            col.customTreeAggregationFinalizerFn = treeAggregationFinalizerFn;
+        });
 
-        this.gridApi.grouping.clearGrouping();
         this.gridApi.grouping.groupColumn('country');
-        this.gridApi.grouping.aggregateColumn('user', this.uiGridGroupingConstants.aggregation.COUNT);
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'country'}), (col) => {
+            col.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.groupVal;
+        });
 
-        if (this._countryGridOptions) {
-            this.gridOptions.categories = this._countryGridOptions.categories;
-            this.gridOptions.columnDefs = this._countryGridOptions.columnDefs;
+        // Pinning left country.
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'country'}), (col) => {
+            this.gridApi.pinning.pinColumn(col, this.uiGridPinningConstants.container.LEFT);
+        });
 
-            return;
-        }
+        // Unpinning country.
+        _.forEach(_.filter(this.gridApi.grid.columns, {name: 'company'}), (col) => {
+            this.gridApi.pinning.pinColumn(col, this.uiGridPinningConstants.container.NONE);
+        });
 
         const _categories = _.cloneDeep(categories);
-        const _columnDefs = _.cloneDeep(columnDefs);
-
-        // Cut country category.
+        // Cut company category.
         const country = _categories.splice(4, 1)[0];
         country.selectable = false;
 
-        // Hide Actions category.
-        _categories.splice(0, 1);
-
-        _.forEach(_.filter(_columnDefs, {displayName: 'Actions'}), (col) => {
-            col.visible = false;
-        });
-
         // Add company as first column.
         _categories.unshift(country);
-
-        _.forEach(_columnDefs, (col) => {
-            col.enableSorting = true;
-
-            if (col.type !== 'number')
-                return;
-
-            col.treeAggregationType = this.uiGridGroupingConstants.aggregation.SUM;
-            col.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.value;
-        });
-
-        // Set grouping to last activity column.
-        const lastactivity = _.find(_columnDefs, { name: 'lastactivity' });
-
-        if (_.nonNil(lastactivity)) {
-            lastactivity.treeAggregationType = this.uiGridGroupingConstants.aggregation.MAX;
-            lastactivity.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.value;
-        }
-
-        this._countryGridOptions = {
-            categories: this.gridOptions.categories = _categories,
-            columnDefs: this.gridOptions.columnDefs = _columnDefs
-        };
+        this.gridOptions.categories = _categories;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug
index 0b8bf7e..b64a177 100644
--- a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug
+++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug
@@ -18,7 +18,7 @@ include /app/helpers/jade/mixins
 
 mixin grid-settings()
     .grid-settings
-        i.fa.fa-cog(data-animation='am-flip-x' bs-dropdown='' aria-haspopup='true' aria-expanded='expanded' data-auto-close='1' data-trigger='click')
+        i.fa.gear-icon(data-animation='am-flip-x' bs-dropdown='' aria-haspopup='true' aria-expanded='expanded' data-auto-close='1' data-trigger='click')
         ul.select.dropdown-menu(role='menu')
             li
                 a(ng-click='$ctrl.gridOptions.selectedAll ? $ctrl.clearAllColumns() : $ctrl.selectAllColumns()')
@@ -51,13 +51,10 @@ mixin grid-settings()
 
     .panel--ignite
         .panel-heading.ui-grid-settings
-            .panel-title(ng-hide='$ctrl.selected.length')
-                span(ng-if='$ctrl.groupBy === "user"') List of registered users
-                span(ng-if='$ctrl.groupBy === "company"') List of registered companies
-                span(ng-if='$ctrl.groupBy === "country"') List of registered countries
-                +grid-settings
-                button.btn.btn--stroke(ng-click='$ctrl.exportCsv()' bs-tooltip data-title='Export table to csv')
-                    i.fa.fa-file-excel-o.export-icon
+            .panel-title
+                +ignite-form-field-bsdropdown('Actions', '$ctrl.action', 'action', '!$ctrl.selected.length', false, '$ctrl.actionOptions')
+                button.btn.btn--stroke(ng-click='$ctrl.exportCsv()' bs-tooltip='' data-title='Export table to csv' data-placement='top')
+                    i.fa.export-icon
                 form.ui-grid-settings-dateperiod(name=form novalidate)
                     -var form = 'admin'
                     +ignite-form-field-datepicker('Period: from', '$ctrl.params.startDate', '"startDate"', null, '$ctrl.params.endDate')
@@ -66,11 +63,13 @@ mixin grid-settings()
                     -var form = 'admin'
                     +ignite-form-field-text('Exclude:', '$ctrl.params.companiesExclude', '"exclude"', false, false, 'Exclude by company name...')
 
-            .panel-selected(ng-show='$ctrl.selected.length')
-                .pull-right
-                    +ignite-form-field-bsdropdown('Actions', '$ctrl.action', 'action', false, false, '$ctrl.actionOptions')
-                div
-                    | {{ $ctrl.selected.length }} item{{ $ctrl.selected.length > 1 ? 's' : '' }} selected
+                .ui-grid-settings--heading(ng-hide='$ctrl.selected.length')
+                    span(ng-if='$ctrl.groupBy === "user"') List of registered users
+                    span(ng-if='$ctrl.groupBy === "company"') List of registered companies
+                    span(ng-if='$ctrl.groupBy === "country"') List of registered countries
+                    +grid-settings
+                .panel-selected(ng-show='$ctrl.selected.length')
+                    | {{ $ctrl.selected.length }} item{{ $ctrl.selected.length > 1 ? 's' : '' }} selected            
 
         .panel-collapse
             .grid.ui-grid--ignite(ui-grid='$ctrl.gridOptions' ui-grid-resize-columns ui-grid-selection ui-grid-exporter ui-grid-pinning ui-grid-grouping)

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/primitives/badge/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/badge/index.scss b/modules/web-console/frontend/app/primitives/badge/index.scss
index 8ce477f..79082e0 100644
--- a/modules/web-console/frontend/app/primitives/badge/index.scss
+++ b/modules/web-console/frontend/app/primitives/badge/index.scss
@@ -29,6 +29,7 @@
   color: white;
   font-family: Roboto;
   font-size: 12px;
+  font-weight: 500;
   text-align: center;
   line-height: 12px;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/primitives/btn/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/btn/index.scss b/modules/web-console/frontend/app/primitives/btn/index.scss
index 1eb027f..ec62df4 100644
--- a/modules/web-console/frontend/app/primitives/btn/index.scss
+++ b/modules/web-console/frontend/app/primitives/btn/index.scss
@@ -19,23 +19,39 @@
     min-width: 36px;
     height: 36px;
 
-    line-height: 36px;
+    line-height: 34px;
     text-align: center;
 
     color: #ee2b27;
     border: 1px solid #ee2b27;
     background: initial;
 
+    i {
+        margin: 0;
+
+        &.export-icon {
+            display: block;
+            width: 16px;
+            height: 16px;
+            margin: auto;
+
+            background-image: url('/images/icons/export.svg');
+            background-repeat: no-repeat;
+            background-position: center;
+        }
+    }
+
     &:hover, &:focus {
         color: #a8110f;
         border-color: #a8110f;
+
+        i {
+            filter: hue-rotate(1deg) saturate(85) brightness(.66);
+        }
     }
 
     &:focus {
         outline: none;
     }
 
-    i {
-        margin: 0;
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/primitives/dropdown/index.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/dropdown/index.pug b/modules/web-console/frontend/app/primitives/dropdown/index.pug
index a6476eb..dfd229c 100644
--- a/modules/web-console/frontend/app/primitives/dropdown/index.pug
+++ b/modules/web-console/frontend/app/primitives/dropdown/index.pug
@@ -32,7 +32,7 @@ mixin ignite-form-field-bsdropdown(label, model, name, disabled, required, optio
             tabindex='0'
             aria-haspopup='true'
             aria-expanded='false'
-        )&attributes(attributes.attributes)
+        )&attributes(attributes)
             a.dropdown-toggle
                 span !{label}
                 span.caret

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/primitives/dropdown/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/dropdown/index.scss b/modules/web-console/frontend/app/primitives/dropdown/index.scss
index e474534..adf87ca 100644
--- a/modules/web-console/frontend/app/primitives/dropdown/index.scss
+++ b/modules/web-console/frontend/app/primitives/dropdown/index.scss
@@ -29,6 +29,8 @@
     .ignite-form-field__control {
         outline: none;
 
+        font-size: 14px;
+
         & > a {
             display: inline-block;
             height: 36px;
@@ -39,7 +41,7 @@
             border-radius: 4px;
 
             color: #de4538;
-            line-height: 36px;
+            line-height: 34px;
 
             .caret {
                 margin-left: 9px;
@@ -78,5 +80,27 @@
                 border-bottom: 1px solid #dddddd;
             }
         }
+
+        &[disabled='disabled'] {
+            opacity: .5;
+
+            & > a {
+                border-color: #c5c5c5;
+
+                color: #393939;
+            }
+
+            &:hover, &:focus {
+                & > a {
+                    border-color: #c5c5c5;
+
+                    color: #393939;
+                }
+            }
+
+            ul {
+                display: none !important;
+            }
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/primitives/panel/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/panel/index.scss b/modules/web-console/frontend/app/primitives/panel/index.scss
index 826d33e..d6cae27 100644
--- a/modules/web-console/frontend/app/primitives/panel/index.scss
+++ b/modules/web-console/frontend/app/primitives/panel/index.scss
@@ -19,7 +19,7 @@
 
 .panel--ignite {
   border: none;
-  border-radius: 0;
+  border-radius: 0 0 4px 4px;
 
   font-family: Roboto;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/primitives/ui-grid-header/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/ui-grid-header/index.scss b/modules/web-console/frontend/app/primitives/ui-grid-header/index.scss
index 4530c02..7b3ce7b 100644
--- a/modules/web-console/frontend/app/primitives/ui-grid-header/index.scss
+++ b/modules/web-console/frontend/app/primitives/ui-grid-header/index.scss
@@ -15,7 +15,11 @@
  * limitations under the License.
  */
 
+@import '../../../public/stylesheets/variables';
+
 .ui-grid-header--subcategories {
+    border-color: $table-border-color;
+
     .ui-grid-row:nth-child(even) .ui-grid-cell.cell-total {
         background-color: rgba(102,175,233,.6);
     }
@@ -34,6 +38,10 @@
         }
     }
 
+    .ui-grid-header-cell:last-child .ui-grid-column-resizer.right {
+        border-color: $table-border-color;
+    }
+
     .ui-grid-header-cell [role="columnheader"] {
         display: flex;
         
@@ -81,7 +89,7 @@
         }
 
         & > div > .ui-grid-cell-contents {
-            border-bottom: 1px solid #d4d4d4;
+            border-bottom: 1px solid $table-border-color;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/primitives/ui-grid-header/index.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/ui-grid-header/index.tpl.pug b/modules/web-console/frontend/app/primitives/ui-grid-header/index.tpl.pug
index 1b91d9e..8a41881 100644
--- a/modules/web-console/frontend/app/primitives/ui-grid-header/index.tpl.pug
+++ b/modules/web-console/frontend/app/primitives/ui-grid-header/index.tpl.pug
@@ -20,10 +20,18 @@
             .ui-grid-header-canvas
                 .ui-grid-header-cell-wrapper(ng-style='colContainer.headerCellWrapperStyle()')
                     .ui-grid-header-cell-row(role='row')
+                        .ui-grid-header-cell.ui-grid-clearfix(
+                            ng-if='col.colDef.name === "treeBaseRowHeaderCol" || col.colDef.name === "selectionRowHeaderCol"'
+                            ng-repeat='col in colContainer.renderedColumns track by col.uid'
+                            ng-class='{ disabled: !grid.options.multiSelect && col.colDef.name === "selectionRowHeaderCol"}'
+
+                            col='col'
+                            ui-grid-header-cell=''
+                            render-index='$index'
+                        )
                         .ui-grid-header-span.ui-grid-header-cell.ui-grid-clearfix.ui-grid-category(ng-repeat='cat in grid.options.categories', ng-if='cat.visible && \
                         (colContainer.renderedColumns | uiGridSubcategories: cat.name).length > 0')
                             div(ng-show='(colContainer.renderedColumns|uiGridSubcategories:cat.name).length > 1')
                                 .ui-grid-cell-contents {{ cat.name }}
                             .ui-grid-header-cell-row
                                 .ui-grid-header-cell.ui-grid-clearfix(ng-repeat='col in (colContainer.renderedColumns|uiGridSubcategories:cat.name) track by col.uid' ui-grid-header-cell='' col='col' render-index='$index')
-                        .ui-grid-header-cell.ui-grid-clearfix(ng-if='col.colDef.name === "treeBaseRowHeaderCol" || col.colDef.name === "selectionRowHeaderCol"' ng-repeat='col in colContainer.renderedColumns track by col.uid' ui-grid-header-cell='' col='col' render-index='$index' ng-class='{ disabled: !grid.options.multiSelect && col.colDef.name === "selectionRowHeaderCol"}')

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/primitives/ui-grid-settings/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/ui-grid-settings/index.scss b/modules/web-console/frontend/app/primitives/ui-grid-settings/index.scss
index 3519eb2..9cd497f 100644
--- a/modules/web-console/frontend/app/primitives/ui-grid-settings/index.scss
+++ b/modules/web-console/frontend/app/primitives/ui-grid-settings/index.scss
@@ -16,6 +16,8 @@
  */
 
 .ui-grid-settings {
+    color: #393939;
+
     ul.select.dropdown-menu {
         padding: 0;
 
@@ -63,7 +65,7 @@
                         content: '';
 
                         position: absolute;
-                        top: 0px;
+                        top: 0;
                         left: 3px;
 
                         width: 4px;
@@ -83,17 +85,16 @@
         }
     }
 
-    .btn {
-        float: right;
+    &--heading > span {
+        position: relative;
+        top: -1px;
+    }
 
+    .btn {
         line-height: 20px;
-        margin-right: 0;
     }
 
     &-filter {
-        float: right;
-        margin-right: 35px;
-
         .ignite-form-field {
             $height: 36px;
 
@@ -123,8 +124,6 @@
     }
 
     &-number-filter {
-        float: right;
-
         .ignite-form-field {
             width: 180px;
             margin-right: 0;
@@ -158,14 +157,51 @@
     }
 
     &-dateperiod {
-        float: right;
         display: block;
         margin-right: 35px;
     }
+
+    .btn.btn--stroke,
+    .dropdown--ignite.ignite-form-field,
+    &-filter,
+    &-number-filter,
+    &-dateperiod {
+        float: right;
+
+        margin-left: 20px;
+        margin-right: 0;
+    }
+
+    &-dateperiod {
+        margin-left: 15px;
+        margin-right: -5px;
+    }
+
+    .grid-settings {
+        i.gear-icon {
+            position: relative;
+            top: 2px;
+
+            display: block;
+            width: 16px;
+            height: 16px;
+            margin: auto;
+
+            background-image: url('/images/icons/gear.svg');
+            background-repeat: no-repeat;
+            background-position: center;
+        }
+
+        &:hover, &:focus {
+            i.gear-icon {
+                filter: hue-rotate(1deg) saturate(85) brightness(.66);
+            }
+        }
+    }
 }
 
 .grid-settings {
     display: inline-block;
 
     margin-left: 10px;
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/app/primitives/ui-grid/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/ui-grid/index.scss b/modules/web-console/frontend/app/primitives/ui-grid/index.scss
index 8e2fbaa..89e5c49 100644
--- a/modules/web-console/frontend/app/primitives/ui-grid/index.scss
+++ b/modules/web-console/frontend/app/primitives/ui-grid/index.scss
@@ -40,10 +40,19 @@
         border-color: transparent;
     }
 
-    .ui-grid-cell-contents {
-        font-family: Roboto;
+    .ui-grid-cell,
+    .ui-grid-header-cell {
+        .ui-grid-cell-contents {
+            padding: 13px 20px;
 
-        padding: 13px 20px;
+            text-align: left;
+            font-family: Roboto;
+        }
+    }
+
+    .ui-grid-contents-wrapper {
+        border-bottom-right-radius: 6px;
+        overflow: hidden;
     }
 
     .ui-grid-render-container-body {
@@ -57,12 +66,6 @@
                     text-align: right;
                 }
             }
-
-            &:first-child {
-                .ui-grid-cell-contents {
-                    padding-left: 0;
-                }            
-            }
         }
     }
 
@@ -70,19 +73,6 @@
         .ui-grid-header-span {
             background: initial;
 
-            &:first-child {
-                .ui-grid-cell-contents {
-                    padding-left: 0;
-                }
-
-                .ng-hide + .ui-grid-header-cell-row {
-                    .ui-grid-cell-contents,
-                    .ui-grid-filter-container {
-                        padding-left: 0;
-                    }
-                }
-            }
-
             .ui-grid-cell-contents {
                 color: $gray-light;
                 font-size: 14px;
@@ -141,21 +131,31 @@
                         width: auto;
                     }
                 }
+
+                &:before {
+                    content: '';
+
+                    position: absolute;
+                    top: 0;
+                    right: 9px;
+                    z-index: 1000;
+                    
+                    width: 5px;
+                    height: 100%;
+                    
+                    opacity: .2;
+                    box-shadow: 2px 0 3px #000;
+                    border-right: 1px solid #000;
+                }
             }
         }
     }
 
     .ui-grid-pinned-container-left .ui-grid-header-cell:last-child {
-        max-width: 52px;
-        min-width: 52px;
-
         border-width: 0;
     }
 
     .ui-grid-pinned-container-left .ui-grid-cell:last-child {
-        min-width: 52px;
-        max-width: 52px;
-
         border-width: 0;
         background-color: initial;
     }
@@ -182,7 +182,7 @@
         &.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell {
             background-color: #e5f2f9;
 
-            box-shadow: 0 -1px 0 0 rgba(117, 117, 117, 0.25), 0 1px 0 0 rgba(117, 117, 117, 0.25);
+            box-shadow: 0 -1px 0 0 #c6cfd8, 0 1px 0 0 #c6cfd8;
         }
     }
 
@@ -305,15 +305,23 @@
             .ui-grid-header-cell-row {
                 .ui-grid-header-cell {
                     border-right: none;
-                    padding-top: 12px;
 
                     &.disabled {
-                        opacity: .5;
+                        opacity: .2;
 
                         .ui-grid-icon-ok {
                             cursor: default;
                         }
                     }
+
+                    &:last-child {
+                        .ui-grid-header-cell {
+                            .ui-grid-column-resizer {
+                                right: -1px;
+                                opacity: 0;
+                            }
+                        }
+                    }
                 }
             }
         }
@@ -322,8 +330,87 @@
             .ui-grid-row {
                 .ui-grid-cell {
                     border-bottom: none;
+
+                    &:nth-child(2) {
+                        overflow: visible;
+                    }
+                }
+            }
+        }
+
+        .ui-grid-tree-header-row {
+            .ui-grid-selection-row-header-buttons {
+                opacity: .2;
+                cursor: default;
+            }
+
+            & ~ .ui-grid-row:not(.ui-grid-tree-header-row) {
+                position: relative;
+
+                &::before {
+                    content: '';
+                    position: absolute;
+                    top: 0;
+                    left: 0;
+                    z-index: 1;
+
+                    width: 4px;
+                    height: 46px;
+                    
+                    background: #0067b9;
+                    box-shadow: 0 -1px 0 0 rgba(0, 0, 0, .3), 0 -1px 0 0 rgba(0, 103, 185, 1);
                 }
             }
         }
     }
+
+    .ui-grid-tree-header-row {
+        font-weight: normal !important;
+    }
+
+    input[type="text"].ui-grid-filter-input {
+        display: block;
+        width: 100%;
+        height: 28px;
+        padding: 3px 3px;
+
+        border: 1px solid #ccc;
+        border-radius: 4px;
+        background-color: #fff;
+        background-image: none;
+
+        color: #393939;
+        text-align: left;
+        font-size: 14px;
+        line-height: 1.42857;
+
+        box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+        transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+
+        &::placeholder {
+            color: #999;
+        }
+
+        &:focus {
+            outline: none;
+
+            box-shadow: none;
+            border-color: #66afe9;
+        }
+    }
+
+    .ui-grid-icon-cancel {
+        &:before {
+            content: '';
+    
+            display: block;
+            width: 16px;
+            height: 16px;
+            margin: 8px 5px;
+
+            background-image: url('/images/icons/cross.svg');
+            background-repeat: no-repeat;
+            background-position: center;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/gulpfile.babel.js/paths.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/gulpfile.babel.js/paths.js b/modules/web-console/frontend/gulpfile.babel.js/paths.js
index 627b2f9..92b354a 100644
--- a/modules/web-console/frontend/gulpfile.babel.js/paths.js
+++ b/modules/web-console/frontend/gulpfile.babel.js/paths.js
@@ -39,6 +39,7 @@ const appModulePaths = [
 ];
 
 const resourcePaths = [
+    './public/**/*.svg',
     './public/**/*.png',
     './public/*.ico'
 ];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/gulpfile.babel.js/tasks/bundle.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/gulpfile.babel.js/tasks/bundle.js b/modules/web-console/frontend/gulpfile.babel.js/tasks/bundle.js
index ac3ac76..07244b9 100644
--- a/modules/web-console/frontend/gulpfile.babel.js/tasks/bundle.js
+++ b/modules/web-console/frontend/gulpfile.babel.js/tasks/bundle.js
@@ -28,7 +28,7 @@ gulp.task('bundle', (cb) => {
     if (process.env.NODE_ENV === 'development') {
         // Important! Call webpack and WebpackDevServer must be inline.
         new WebpackDevServer(webpack(webpackConfig), devServerConfig)
-            .listen(devServerConfig.port, 'localhost', cb);
+            .listen(devServerConfig.port, devServerConfig.host || 'localhost', cb);
     }
     else
         webpack(webpackConfig, cb);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js b/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
index c837c43..87094a8 100644
--- a/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
+++ b/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
@@ -18,7 +18,8 @@
 import {destDir} from '../../paths';
 
 const backendPort = 3000;
-const devServerPort = 9000;
+const devServerPort = process.env.PORT || 9000;
+const devServerHost = process.env.HOST;
 
 export default {
     devtool: 'source-map',
@@ -56,6 +57,7 @@ export default {
             colors: true,
             chunks: false
         },
+        host: devServerHost,
         port: devServerPort
     }
 };

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/public/images/icons/cross.svg
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/images/icons/cross.svg b/modules/web-console/frontend/public/images/icons/cross.svg
new file mode 100644
index 0000000..1a10375
--- /dev/null
+++ b/modules/web-console/frontend/public/images/icons/cross.svg
@@ -0,0 +1 @@
+<svg id="cross-icon" width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path fill="#757575" d="M10.791 0L6 4.791 1.209 0 0 1.209 4.791 6 0 10.791 1.209 12 6 7.209 10.791 12 12 10.791 7.209 6 12 1.209z" fill-rule="evenodd"/></svg>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/public/images/icons/export.svg
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/images/icons/export.svg b/modules/web-console/frontend/public/images/icons/export.svg
new file mode 100644
index 0000000..359c3df
--- /dev/null
+++ b/modules/web-console/frontend/public/images/icons/export.svg
@@ -0,0 +1 @@
+<svg id="export-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#ee2b27" d="M10.4 61.6v380.8l280.1 49.8V11.8L10.4 61.6zm161 270.5l-23.5-61.7-23.1 58.5H92.7l37.5-81.6-34.8-80h33l21.3 55.2 25.3-59.9 31.7-1.6-39.6 85.5 41.2 88.3-36.9-2.7zM489.3 61.1H300v27.8h71.2V139H300v15.1h71.2v50.1H300v15.1h71.2v50.1H300v15.1h71.2v50.2H300v15.4h71.2v50.1H300v32.2h189.3c5.4 0 9.7-4.5 9.7-10V71.2c0-5.6-4.4-10.1-9.7-10.1zm-23.1 339.2h-80.3v-50.1h80.3v50.1zm0-65.5h-80.3v-50.2h80.3v50.2zm0-65.2h-80.3v-50.1h80.3v50.1zm0-65.3h-80.3v-50.2h80.3v50.2zm0-65.2h-80.3V88.9h80.3v50.2z"/></svg>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/public/images/icons/gear.svg
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/images/icons/gear.svg b/modules/web-console/frontend/public/images/icons/gear.svg
new file mode 100644
index 0000000..a9a7269
--- /dev/null
+++ b/modules/web-console/frontend/public/images/icons/gear.svg
@@ -0,0 +1 @@
+<svg id="gear-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.st0{fill:#424242}</style><path class="st0" d="M14.1 8.8c0-.3.1-.5.1-.8 0-.3 0-.5-.1-.8l1.7-1.3c.2-.1.2-.3.1-.5l-1.6-2.8c-.1-.2-.3-.2-.5-.2l-2 .8c-.4-.3-.9-.6-1.4-.8L10.1.3C10 .1 9.8 0 9.6 0H6.4c-.3 0-.4.1-.5.3l-.3 2.2c-.5.2-1 .5-1.4.8l-2-.8c-.2-.1-.4-.1-.5.1L.1 5.4c-.1.2-.1.4.1.5l1.7 1.3c0 .3-.1.5-.1.8 0 .3 0 .5.1.8L.2 10.1c-.2.1-.2.3-.1.5l1.6 2.8c.1.2.3.2.5.2l2-.8c.4.3.9.6 1.4.8l.3 2.1c.1.2.2.3.5.3h3.3c.2 0 .4-.1.4-.3l.3-2.1c.5-.2 1-.5 1.4-.8l2 .8c.2.1.4 0 .5-.2l1.6-2.8c.1-.2.1-.4-.1-.5l-1.7-1.3zM8 11c-1.7 0-3-1.3-3-3s1.3-3 3-3 3 1.3 3 3-1.3 3-3 3z"/></svg>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/frontend/public/stylesheets/_bootstrap-variables.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/_bootstrap-variables.scss b/modules/web-console/frontend/public/stylesheets/_bootstrap-variables.scss
index e308de3..d6a51e3 100644
--- a/modules/web-console/frontend/public/stylesheets/_bootstrap-variables.scss
+++ b/modules/web-console/frontend/public/stylesheets/_bootstrap-variables.scss
@@ -29,7 +29,7 @@ $gray-base:              #000 !default;
 $gray-darker:            lighten($gray-base, 13.5%) !default; // #222
 $gray-dark:              lighten($gray-base, 20%) !default;   // #333
 $gray:                   lighten($gray-base, 33.5%) !default; // #555
-$gray-light:             lighten($gray-base, 46.7%) !default; // #777
+$gray-light:             lighten($gray-base, 46%) !default;   // #757575
 $gray-lighter:           lighten($gray-base, 93.5%) !default; // #eee
 
 $brand-primary:         #ec1c24 !default;
@@ -46,7 +46,7 @@ $brand-danger:          #d9534f !default;
 //** Background color for `<body>`.
 $body-bg:               #f9f9f9 !default;
 //** Global text color on `<body>`.
-$text-color:            $gray-dark !default;
+$text-color:            #393939 !default;
 
 //** Global textual link color.
 $link-color:            $brand-primary !default;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c829aaca/modules/web-console/licenses/cc-by-3.0.txt
----------------------------------------------------------------------
diff --git a/modules/web-console/licenses/cc-by-3.0.txt b/modules/web-console/licenses/cc-by-3.0.txt
new file mode 100644
index 0000000..bd32fa8
--- /dev/null
+++ b/modules/web-console/licenses/cc-by-3.0.txt
@@ -0,0 +1,319 @@
+Creative Commons Legal Code
+
+Attribution 3.0 Unported
+
+    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+    LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
+    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+    REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
+    DAMAGES RESULTING FROM ITS USE.
+
+License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+CONDITIONS.
+
+1. Definitions
+
+ a. "Adaptation" means a work based upon the Work, or upon the Work and
+    other pre-existing works, such as a translation, adaptation,
+    derivative work, arrangement of music or other alterations of a
+    literary or artistic work, or phonogram or performance and includes
+    cinematographic adaptations or any other form in which the Work may be
+    recast, transformed, or adapted including in any form recognizably
+    derived from the original, except that a work that constitutes a
+    Collection will not be considered an Adaptation for the purpose of
+    this License. For the avoidance of doubt, where the Work is a musical
+    work, performance or phonogram, the synchronization of the Work in
+    timed-relation with a moving image ("synching") will be considered an
+    Adaptation for the purpose of this License.
+ b. "Collection" means a collection of literary or artistic works, such as
+    encyclopedias and anthologies, or performances, phonograms or
+    broadcasts, or other works or subject matter other than works listed
+    in Section 1(f) below, which, by reason of the selection and
+    arrangement of their contents, constitute intellectual creations, in
+    which the Work is included in its entirety in unmodified form along
+    with one or more other contributions, each constituting separate and
+    independent works in themselves, which together are assembled into a
+    collective whole. A work that constitutes a Collection will not be
+    considered an Adaptation (as defined above) for the purposes of this
+    License.
+ c. "Distribute" means to make available to the public the original and
+    copies of the Work or Adaptation, as appropriate, through sale or
+    other transfer of ownership.
+ d. "Licensor" means the individual, individuals, entity or entities that
+    offer(s) the Work under the terms of this License.
+ e. "Original Author" means, in the case of a literary or artistic work,
+    the individual, individuals, entity or entities who created the Work
+    or if no individual or entity can be identified, the publisher; and in
+    addition (i) in the case of a performance the actors, singers,
+    musicians, dancers, and other persons who act, sing, deliver, declaim,
+    play in, interpret or otherwise perform literary or artistic works or
+    expressions of folklore; (ii) in the case of a phonogram the producer
+    being the person or legal entity who first fixes the sounds of a
+    performance or other sounds; and, (iii) in the case of broadcasts, the
+    organization that transmits the broadcast.
+ f. "Work" means the literary and/or artistic work offered under the terms
+    of this License including without limitation any production in the
+    literary, scientific and artistic domain, whatever may be the mode or
+    form of its expression including digital form, such as a book,
+    pamphlet and other writing; a lecture, address, sermon or other work
+    of the same nature; a dramatic or dramatico-musical work; a
+    choreographic work or entertainment in dumb show; a musical
+    composition with or without words; a cinematographic work to which are
+    assimilated works expressed by a process analogous to cinematography;
+    a work of drawing, painting, architecture, sculpture, engraving or
+    lithography; a photographic work to which are assimilated works
+    expressed by a process analogous to photography; a work of applied
+    art; an illustration, map, plan, sketch or three-dimensional work
+    relative to geography, topography, architecture or science; a
+    performance; a broadcast; a phonogram; a compilation of data to the
+    extent it is protected as a copyrightable work; or a work performed by
+    a variety or circus performer to the extent it is not otherwise
+    considered a literary or artistic work.
+ g. "You" means an individual or entity exercising rights under this
+    License who has not previously violated the terms of this License with
+    respect to the Work, or who has received express permission from the
+    Licensor to exercise rights under this License despite a previous
+    violation.
+ h. "Publicly Perform" means to perform public recitations of the Work and
+    to communicate to the public those public recitations, by any means or
+    process, including by wire or wireless means or public digital
+    performances; to make available to the public Works in such a way that
+    members of the public may access these Works from a place and at a
+    place individually chosen by them; to perform the Work to the public
+    by any means or process and the communication to the public of the
+    performances of the Work, including by public digital performance; to
+    broadcast and rebroadcast the Work by any means including signs,
+    sounds or images.
+ i. "Reproduce" means to make copies of the Work by any means including
+    without limitation by sound or visual recordings and the right of
+    fixation and reproducing fixations of the Work, including storage of a
+    protected performance or phonogram in digital form or other electronic
+    medium.
+
+2. Fair Dealing Rights. Nothing in this License is intended to reduce,
+limit, or restrict any uses free from copyright or rights arising from
+limitations or exceptions that are provided for in connection with the
+copyright protection under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License,
+Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+perpetual (for the duration of the applicable copyright) license to
+exercise the rights in the Work as stated below:
+
+ a. to Reproduce the Work, to incorporate the Work into one or more
+    Collections, and to Reproduce the Work as incorporated in the
+    Collections;
+ b. to create and Reproduce Adaptations provided that any such Adaptation,
+    including any translation in any medium, takes reasonable steps to
+    clearly label, demarcate or otherwise identify that changes were made
+    to the original Work. For example, a translation could be marked "The
+    original work was translated from English to Spanish," or a
+    modification could indicate "The original work has been modified.";
+ c. to Distribute and Publicly Perform the Work including as incorporated
+    in Collections; and,
+ d. to Distribute and Publicly Perform Adaptations.
+ e. For the avoidance of doubt:
+
+     i. Non-waivable Compulsory License Schemes. In those jurisdictions in
+        which the right to collect royalties through any statutory or
+        compulsory licensing scheme cannot be waived, the Licensor
+        reserves the exclusive right to collect such royalties for any
+        exercise by You of the rights granted under this License;
+    ii. Waivable Compulsory License Schemes. In those jurisdictions in
+        which the right to collect royalties through any statutory or
+        compulsory licensing scheme can be waived, the Licensor waives the
+        exclusive right to collect such royalties for any exercise by You
+        of the rights granted under this License; and,
+   iii. Voluntary License Schemes. The Licensor waives the right to
+        collect royalties, whether individually or, in the event that the
+        Licensor is a member of a collecting society that administers
+        voluntary licensing schemes, via that society, from any exercise
+        by You of the rights granted under this License.
+
+The above rights may be exercised in all media and formats whether now
+known or hereafter devised. The above rights include the right to make
+such modifications as are technically necessary to exercise the rights in
+other media and formats. Subject to Section 8(f), all rights not expressly
+granted by Licensor are hereby reserved.
+
+4. Restrictions. The license granted in Section 3 above is expressly made
+subject to and limited by the following restrictions:
+
+ a. You may Distribute or Publicly Perform the Work only under the terms
+    of this License. You must include a copy of, or the Uniform Resource
+    Identifier (URI) for, this License with every copy of the Work You
+    Distribute or Publicly Perform. You may not offer or impose any terms
+    on the Work that restrict the terms of this License or the ability of
+    the recipient of the Work to exercise the rights granted to that
+    recipient under the terms of the License. You may not sublicense the
+    Work. You must keep intact all notices that refer to this License and
+    to the disclaimer of warranties with every copy of the Work You
+    Distribute or Publicly Perform. When You Distribute or Publicly
+    Perform the Work, You may not impose any effective technological
+    measures on the Work that restrict the ability of a recipient of the
+    Work from You to exercise the rights granted to that recipient under
+    the terms of the License. This Section 4(a) applies to the Work as
+    incorporated in a Collection, but this does not require the Collection
+    apart from the Work itself to be made subject to the terms of this
+    License. If You create a Collection, upon notice from any Licensor You
+    must, to the extent practicable, remove from the Collection any credit
+    as required by Section 4(b), as requested. If You create an
+    Adaptation, upon notice from any Licensor You must, to the extent
+    practicable, remove from the Adaptation any credit as required by
+    Section 4(b), as requested.
+ b. If You Distribute, or Publicly Perform the Work or any Adaptations or
+    Collections, You must, unless a request has been made pursuant to
+    Section 4(a), keep intact all copyright notices for the Work and
+    provide, reasonable to the medium or means You are utilizing: (i) the
+    name of the Original Author (or pseudonym, if applicable) if supplied,
+    and/or if the Original Author and/or Licensor designate another party
+    or parties (e.g., a sponsor institute, publishing entity, journal) for
+    attribution ("Attribution Parties") in Licensor's copyright notice,
+    terms of service or by other reasonable means, the name of such party
+    or parties; (ii) the title of the Work if supplied; (iii) to the
+    extent reasonably practicable, the URI, if any, that Licensor
+    specifies to be associated with the Work, unless such URI does not
+    refer to the copyright notice or licensing information for the Work;
+    and (iv) , consistent with Section 3(b), in the case of an Adaptation,
+    a credit identifying the use of the Work in the Adaptation (e.g.,
+    "French translation of the Work by Original Author," or "Screenplay
+    based on original Work by Original Author"). The credit required by
+    this Section 4 (b) may be implemented in any reasonable manner;
+    provided, however, that in the case of a Adaptation or Collection, at
+    a minimum such credit will appear, if a credit for all contributing
+    authors of the Adaptation or Collection appears, then as part of these
+    credits and in a manner at least as prominent as the credits for the
+    other contributing authors. For the avoidance of doubt, You may only
+    use the credit required by this Section for the purpose of attribution
+    in the manner set out above and, by exercising Your rights under this
+    License, You may not implicitly or explicitly assert or imply any
+    connection with, sponsorship or endorsement by the Original Author,
+    Licensor and/or Attribution Parties, as appropriate, of You or Your
+    use of the Work, without the separate, express prior written
+    permission of the Original Author, Licensor and/or Attribution
+    Parties.
+ c. Except as otherwise agreed in writing by the Licensor or as may be
+    otherwise permitted by applicable law, if You Reproduce, Distribute or
+    Publicly Perform the Work either by itself or as part of any
+    Adaptations or Collections, You must not distort, mutilate, modify or
+    take other derogatory action in relation to the Work which would be
+    prejudicial to the Original Author's honor or reputation. Licensor
+    agrees that in those jurisdictions (e.g. Japan), in which any exercise
+    of the right granted in Section 3(b) of this License (the right to
+    make Adaptations) would be deemed to be a distortion, mutilation,
+    modification or other derogatory action prejudicial to the Original
+    Author's honor and reputation, the Licensor will waive or not assert,
+    as appropriate, this Section, to the fullest extent permitted by the
+    applicable national law, to enable You to reasonably exercise Your
+    right under Section 3(b) of this License (right to make Adaptations)
+    but not otherwise.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
+OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
+LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
+ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
+ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ a. This License and the rights granted hereunder will terminate
+    automatically upon any breach by You of the terms of this License.
+    Individuals or entities who have received Adaptations or Collections
+    from You under this License, however, will not have their licenses
+    terminated provided such individuals or entities remain in full
+    compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+    survive any termination of this License.
+ b. Subject to the above terms and conditions, the license granted here is
+    perpetual (for the duration of the applicable copyright in the Work).
+    Notwithstanding the above, Licensor reserves the right to release the
+    Work under different license terms or to stop distributing the Work at
+    any time; provided, however that any such election will not serve to
+    withdraw this License (or any other license that has been, or is
+    required to be, granted under the terms of this License), and this
+    License will continue in full force and effect unless terminated as
+    stated above.
+
+8. Miscellaneous
+
+ a. Each time You Distribute or Publicly Perform the Work or a Collection,
+    the Licensor offers to the recipient a license to the Work on the same
+    terms and conditions as the license granted to You under this License.
+ b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+    offers to the recipient a license to the original Work on the same
+    terms and conditions as the license granted to You under this License.
+ c. If any provision of this License is invalid or unenforceable under
+    applicable law, it shall not affect the validity or enforceability of
+    the remainder of the terms of this License, and without further action
+    by the parties to this agreement, such provision shall be reformed to
+    the minimum extent necessary to make such provision valid and
+    enforceable.
+ d. No term or provision of this License shall be deemed waived and no
+    breach consented to unless such waiver or consent shall be in writing
+    and signed by the party to be charged with such waiver or consent.
+ e. This License constitutes the entire agreement between the parties with
+    respect to the Work licensed here. There are no understandings,
+    agreements or representations with respect to the Work not specified
+    here. Licensor shall not be bound by any additional provisions that
+    may appear in any communication from You. This License may not be
+    modified without the mutual written agreement of the Licensor and You.
+ f. The rights granted under, and the subject matter referenced, in this
+    License were drafted utilizing the terminology of the Berne Convention
+    for the Protection of Literary and Artistic Works (as amended on
+    September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
+    Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
+    and the Universal Copyright Convention (as revised on July 24, 1971).
+    These rights and subject matter take effect in the relevant
+    jurisdiction in which the License terms are sought to be enforced
+    according to the corresponding provisions of the implementation of
+    those treaty provisions in the applicable national law. If the
+    standard suite of rights granted under applicable copyright law
+    includes additional rights not granted under this License, such
+    additional rights are deemed to be included in the License; this
+    License is not intended to restrict the license of any rights under
+    applicable law.
+
+
+Creative Commons Notice
+
+    Creative Commons is not a party to this License, and makes no warranty
+    whatsoever in connection with the Work. Creative Commons will not be
+    liable to You or any party on any legal theory for any damages
+    whatsoever, including without limitation any general, special,
+    incidental or consequential damages arising in connection to this
+    license. Notwithstanding the foregoing two (2) sentences, if Creative
+    Commons has expressly identified itself as the Licensor hereunder, it
+    shall have all rights and obligations of Licensor.
+
+    Except for the limited purpose of indicating to the public that the
+    Work is licensed under the CCPL, Creative Commons does not authorize
+    the use by either party of the trademark "Creative Commons" or any
+    related trademark or logo of Creative Commons without the prior
+    written consent of Creative Commons. Any permitted use will be in
+    compliance with Creative Commons' then-current trademark usage
+    guidelines, as may be published on its website or otherwise made
+    available upon request from time to time. For the avoidance of doubt,
+    this trademark restriction does not form part of this License.
+
+    Creative Commons may be contacted at https://creativecommons.org/.
\ No newline at end of file


Mime
View raw message