You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2018/10/08 03:34:47 UTC

ignite git commit: IGNITE-9809 Web Console: Minor fixes.

Repository: ignite
Updated Branches:
  refs/heads/master 76daf05fe -> 1ec9ee438


IGNITE-9809 Web Console: Minor fixes.


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

Branch: refs/heads/master
Commit: 1ec9ee43884ccafd0ebbb2cbcfbd596ce79dbfd6
Parents: 76daf05
Author: Andrey Novikov <an...@apache.org>
Authored: Mon Oct 8 10:34:46 2018 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Mon Oct 8 10:34:46 2018 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/app/app.config.js  |   3 +-
 .../app/components/bs-select-menu/style.scss    |   2 +-
 .../components/cluster-selector/template.pug    |   2 +-
 .../list-editable-cols/row.directive.js         |   5 +-
 .../components/page-queries/notebook.service.js |   2 +-
 .../components/web-console-header/component.js  |   4 +
 .../components/web-console-header/template.pug  |   5 +-
 .../app/core/activities/Activities.data.js      |   5 +-
 modules/web-console/frontend/app/data/i18n.js   | 256 ++++++++++++++++++-
 .../frontend/app/filters/duration.filter.js     |   6 +-
 .../app/modules/agent/AgentManager.service.js   |  15 +-
 .../frontend/app/modules/user/User.service.js   |   7 +
 .../frontend/app/modules/user/user.module.js    |  21 +-
 .../frontend/app/primitives/tooltip/index.scss  |   2 +-
 .../frontend/app/services/FormUtils.service.js  |   2 +-
 .../frontend/app/services/exceptionHandler.js   |   4 +
 modules/web-console/frontend/package.json       |   5 +-
 .../stylesheets/_bootstrap-variables.scss       |   2 +-
 .../frontend/public/stylesheets/style.scss      |   1 -
 19 files changed, 316 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/app.config.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.config.js b/modules/web-console/frontend/app/app.config.js
index e2bc057..88bffee 100644
--- a/modules/web-console/frontend/app/app.config.js
+++ b/modules/web-console/frontend/app/app.config.js
@@ -15,8 +15,8 @@
  * limitations under the License.
  */
 
-import _ from 'lodash';
 import angular from 'angular';
+
 import negate from 'lodash/negate';
 import isNil from 'lodash/isNil';
 import isEmpty from 'lodash/isEmpty';
@@ -133,4 +133,3 @@ igniteConsoleCfg.directive('uiGridSelection', function() {
         }
     };
 });
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/components/bs-select-menu/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/bs-select-menu/style.scss b/modules/web-console/frontend/app/components/bs-select-menu/style.scss
index ac3991b..ac3f7aa 100644
--- a/modules/web-console/frontend/app/components/bs-select-menu/style.scss
+++ b/modules/web-console/frontend/app/components/bs-select-menu/style.scss
@@ -99,4 +99,4 @@
     bottom: 0;
     left: 0;
     z-index: 1999;
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/components/cluster-selector/template.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/cluster-selector/template.pug b/modules/web-console/frontend/app/components/cluster-selector/template.pug
index f1e80db..39c1af2 100644
--- a/modules/web-console/frontend/app/components/cluster-selector/template.pug
+++ b/modules/web-console/frontend/app/components/cluster-selector/template.pug
@@ -45,7 +45,7 @@ span(data-ng-if='!$ctrl.isDemo && $ctrl.clusters.length > 1')
         aria-expanded='false'
     )
         span(ng-if='!$ctrl.cluster') No clusters available
-        
+
         span(ng-if='$ctrl.cluster')
             cluster-security-icon(secured='$ctrl.cluster.secured')
             | {{ $ctrl.cluster.name }}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/components/list-editable/components/list-editable-cols/row.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/list-editable/components/list-editable-cols/row.directive.js b/modules/web-console/frontend/app/components/list-editable/components/list-editable-cols/row.directive.js
index 2753263..8f38331 100644
--- a/modules/web-console/frontend/app/components/list-editable/components/list-editable-cols/row.directive.js
+++ b/modules/web-console/frontend/app/components/list-editable/components/list-editable-cols/row.directive.js
@@ -15,6 +15,8 @@
  * limitations under the License.
  */
 
+import {nonEmpty} from 'app/utils/lodashMixins';
+
 import {ListEditableColsController} from './cols.directive';
 
 /** @returns {ng.IDirective} */
@@ -35,7 +37,8 @@ export default function() {
                 el.addClass(ctrl.rowClass);
 
             ctrl.colDefs.forEach(({ cellClass }, index) => {
-                _.forEach((Array.isArray(cellClass) ? cellClass : [cellClass]), (item) => children[index].classList.add(item));
+                if (nonEmpty(cellClass))
+                    children[index].classList.add(...(Array.isArray(cellClass) ? cellClass : cellClass.split(' ')));
             });
         }
     };

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/components/page-queries/notebook.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/page-queries/notebook.service.js b/modules/web-console/frontend/app/components/page-queries/notebook.service.js
index dbfd6a6..2a60cdc 100644
--- a/modules/web-console/frontend/app/components/page-queries/notebook.service.js
+++ b/modules/web-console/frontend/app/components/page-queries/notebook.service.js
@@ -70,7 +70,7 @@ export default class Notebook {
         return this.confirmModal.confirm(`Are you sure you want to remove notebook: "${notebook.name}"?`)
             .then(() => this.NotebookData.findIndex(notebook))
             .then((idx) => {
-                this.NotebookData.remove(notebook)
+                return this.NotebookData.remove(notebook)
                     .then(() => {
                         if (this.$state.includes('base.sql.tabs.notebook') && this.$state.params.noteId === notebook._id)
                             return this._openNotebook(idx);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/components/web-console-header/component.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/web-console-header/component.js b/modules/web-console/frontend/app/components/web-console-header/component.js
index a0a8230..02b3080 100644
--- a/modules/web-console/frontend/app/components/web-console-header/component.js
+++ b/modules/web-console/frontend/app/components/web-console-header/component.js
@@ -36,6 +36,10 @@ export default {
                 !this.constructor.connectedClustersUnvisibleStates.some((state) => this.$state.includes(state));
         }
 
+        isAuthorized() {
+            return !!this.$rootScope.user;
+        }
+
         $onInit() {
             this.setConnectedClustersVisible();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/components/web-console-header/template.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/web-console-header/template.pug b/modules/web-console/frontend/app/components/web-console-header/template.pug
index 801b742..1d25b13 100644
--- a/modules/web-console/frontend/app/components/web-console-header/template.pug
+++ b/modules/web-console/frontend/app/components/web-console-header/template.pug
@@ -26,7 +26,10 @@
 .wch-content
     connected-clusters(ng-if='$ctrl.$rootScope.user && !$ctrl.$rootScope.IgniteDemoMode && $ctrl.isConnectedClustersVisible && !$root.user.becomeUsed')
 
-    a(ui-sref='landing')
+    a(ui-sref='default-state' ng-if='$ctrl.isAuthorized()').wch-logo-anchor
+        img.wch-logo(ng-src='{{::$ctrl.branding.headerLogo}}')
+
+    a(ui-sref='landing' ng-if='!$ctrl.isAuthorized()').wch-logo-anchor
         img.wch-logo(ng-src='{{::$ctrl.branding.headerLogo}}')
 
     .wch-slot.wch-slot-left(ng-transclude='slotLeft')

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/core/activities/Activities.data.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/core/activities/Activities.data.js b/modules/web-console/frontend/app/core/activities/Activities.data.js
index 35b44e6..8786816 100644
--- a/modules/web-console/frontend/app/core/activities/Activities.data.js
+++ b/modules/web-console/frontend/app/core/activities/Activities.data.js
@@ -35,6 +35,9 @@ export default class ActivitiesData {
         action = action || this.$state.$current.url.source || '';
         group = group || (action.match(/^\/([^/]+)/) || [])[1];
 
-        return this.$http.post('/api/v1/activities/page', { group, action });
+        return this.$http.post('/api/v1/activities/page', { group, action })
+            .catch(() => {
+                // No-op.
+            });
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/data/i18n.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/i18n.js b/modules/web-console/frontend/app/data/i18n.js
index e21b8c5..e6c1294 100644
--- a/modules/web-console/frontend/app/data/i18n.js
+++ b/modules/web-console/frontend/app/data/i18n.js
@@ -43,5 +43,259 @@ export default {
     '/queries/notebook/': 'Query notebook',
     '/settings/profile': 'User profile',
     '/settings/admin': 'Admin panel',
-    '/logout': 'Logout'
+    '/logout': 'Logout',
+
+    // app/components/page-signin/template.pug
+    'app.components.page-signin.m1': 'Sign In',
+    'app.components.page-signin.m2': 'Email:',
+    'app.components.page-signin.m3': 'Input email',
+    'app.components.page-signin.m4': 'Password:',
+    'app.components.page-signin.m5': 'Input password',
+    'app.components.page-signin.m6': 'Forgot password?',
+    'app.components.page-signin.m7': 'Sign In',
+    'app.components.page-signin.m8': 'Don\'t have an account? #[a(ui-sref=\'signup\') Get started]',
+    // app/components/page-signin/run.js
+    'app.components.page-signin.m9': 'Sign In',
+
+
+    // app/components/page-queries/template.tpl.pug
+    'app.components.page-queries.m1': 'Show data in tabular form',
+    'app.components.page-queries.m2': 'Show bar chart<br/>By default first column - X values, second column - Y values<br/>In case of one column it will be treated as Y values',
+    'app.components.page-queries.m3': 'Show pie chart<br/>By default first column - pie labels, second column - pie values<br/>In case of one column it will be treated as pie values',
+    'app.components.page-queries.m4': 'Show line chart<br/>By default first column - X values, second column - Y values<br/>In case of one column it will be treated as Y values',
+    'app.components.page-queries.m5': 'Show area chart<br/>By default first column - X values, second column - Y values<br/>In case of one column it will be treated as Y values',
+    'app.components.page-queries.m6': 'Click to show chart settings dialog',
+    'app.components.page-queries.m7': 'Chart settings',
+    'app.components.page-queries.m8': 'Show',
+    'app.components.page-queries.m9': 'min',
+    'app.components.page-queries.m10': 'Duration: #[b {{paragraph.duration | duration}}]',
+    'app.components.page-queries.m11': 'NodeID8: #[b {{paragraph.resNodeId | id8}}]',
+    'app.components.page-queries.m12': 'Rename notebook',
+    'app.components.page-queries.m13': 'Remove notebook',
+    'app.components.page-queries.m14': 'Save notebook name',
+    'app.components.page-queries.m15': 'Scroll to query',
+    'app.components.page-queries.m16': 'Add query',
+    'app.components.page-queries.m17': 'Add scan',
+    'app.components.page-queries.m18': 'Failed to load notebook',
+    'app.components.page-queries.m19': 'Notebook not accessible any more. Leave notebooks or open another notebook.',
+    'app.components.page-queries.m20': 'Leave notebooks',
+    'app.components.page-queries.m21': 'Rename query',
+    'app.components.page-queries.m22': 'Rename query',
+    'app.components.page-queries.m23': 'Remove query',
+    'app.components.page-queries.m24': 'Save query name',
+    'app.components.page-queries.m25': 'Configure periodical execution of last successfully executed query',
+    'app.components.page-queries.m26': 'Refresh rate:',
+    'app.components.page-queries.m27': 'Max number of rows to show in query result as one page',
+    'app.components.page-queries.m28': 'Page size:',
+    'app.components.page-queries.m29': 'Limit query max results to specified number of pages',
+    'app.components.page-queries.m30': 'Max pages:',
+    'app.components.page-queries.m31': 'Non-collocated joins is a special mode that allow to join data across cluster without collocation.<br/>Nested joins are not supported for now.<br/><b>NOTE</b>: In some cases it may consume more heap memory or may take a long time than collocated joins.',
+    'app.components.page-queries.m32': 'Allow non-collocated joins',
+    'app.components.page-queries.m33': 'Enforce join order of tables in the query.<br/>If <b>set</b>, then query optimizer will not reorder tables within join.<br/><b>NOTE:</b> It is not recommended to enable this property unless you have verified that indexes are not selected in optimal order.',
+    'app.components.page-queries.m34': 'Enforce join order',
+    'app.components.page-queries.m35': 'By default Ignite attempts to fetch the whole query result set to memory and send it to the client.<br/>For small and medium result sets this provides optimal performance and minimize duration of internal database locks, thus increasing concurrency.<br/>If result set is too big to fit in available memory this could lead to excessive GC pauses and even OutOfMemoryError.<br/>Use this flag as a hint for Ignite to fetch result set lazily, thus minimizing memory consumption at the cost of moderate performance hit.',
+    'app.components.page-queries.m36': 'Lazy result set',
+    'app.components.page-queries.m37': 'Execute',
+    'app.components.page-queries.m38': 'Execute on selected node',
+    'app.components.page-queries.m39': '{{queryTooltip(paragraph, "explain query")}}',
+    'app.components.page-queries.m40': 'Explain',
+    'app.components.page-queries.m41': 'Page: #[b {{paragraph.page}}]',
+    'app.components.page-queries.m42': 'Results so far: #[b {{paragraph.rows.length + paragraph.total}}]',
+    'app.components.page-queries.m43': 'Duration: #[b {{paragraph.duration | duration}}]',
+    'app.components.page-queries.m44': 'NodeID8: #[b {{paragraph.resNodeId | id8}}]',
+    'app.components.page-queries.m45': '{{ queryTooltip(paragraph, "export query results") }}',
+    'app.components.page-queries.m46': 'Export',
+    'app.components.page-queries.m47': 'Export',
+    'app.components.page-queries.m48': 'Export all',
+    'app.components.page-queries.m49': 'Copy current result page to clipboard',
+    'app.components.page-queries.m50': 'Copy to clipboard',
+    'app.components.page-queries.m51': 'Page: #[b {{paragraph.pa',
+    'app.components.page-queries.m52': 'Results so far: #[b {{paragraph.rows.length + paragraph.total}}]',
+    'app.components.page-queries.m53': 'Duration: #[b {{paragraph.duration | duration}}]',
+    'app.components.page-queries.m54': 'NodeID8: #[b {{paragraph.resNodeId | id8}}]',
+    'app.components.page-queries.m55': 'Export',
+    'app.components.page-queries.m56': 'Export',
+    'app.components.page-queries.m57': 'Export all',
+    'app.components.page-queries.m58': 'Copy current result page to clipboard',
+    'app.components.page-queries.m59': 'Copy to clipboard',
+    'app.components.page-queries.m60': 'Cannot display chart. Please configure axis using #[b Chart settings]',
+    'app.components.page-queries.m61': 'Cannot display chart. Result set must contain Java build-in type columns. Please change query and execute it again.',
+    'app.components.page-queries.m62': 'Pie chart does not support \'TIME_LINE\' column for X-axis. Please use another column for X-axis or switch to another chart.',
+    'app.components.page-queries.m63': 'Charts do not support #[b Explain] and #[b Scan] query',
+    'app.components.page-queries.m64': 'Cache:',
+    'app.components.page-queries.m65': 'Choose cache',
+    'app.components.page-queries.m66': 'Filter:',
+    'app.components.page-queries.m67': 'Enter filter',
+    'app.components.page-queries.m68': 'Select this checkbox for case sensitive search',
+    'app.components.page-queries.m69': 'Max number of rows to show in query result as one page',
+    'app.components.page-queries.m70': 'Page size:',
+    'app.components.page-queries.m71': 'Scan',
+    'app.components.page-queries.m72': 'Scan on selected node',
+    'app.components.page-queries.m73': 'Error: {{paragraph.error.message}}',
+    'app.components.page-queries.m74': 'Result set is empty. Duration: #[b {{paragraph.duration | duration}}]',
+    'app.components.page-queries.m75': 'Showing results for scan of #[b {{ paragraph.queryArgs.cacheName | defaultName }}]',
+    'app.components.page-queries.m76': '&nbsp; with filter: #[b {{ paragraph.queryArgs.filter }}]',
+    'app.components.page-queries.m77': '&nbsp; on node: #[b {{ paragraph.queryArgs.localNid | limitTo:8 }}]',
+    'app.components.page-queries.m78': 'Next',
+    'app.components.page-queries.m79': 'Caches:',
+    'app.components.page-queries.m80': 'Click to show cache types metadata dialog',
+    'app.components.page-queries.m81': 'Filter caches...',
+    'app.components.page-queries.m82': 'Use selected cache as default schema name.<br/>This will allow to execute query on specified cache without specify schema name.<br/><b>NOTE:</b> In future version of Ignite this feature will be removed.',
+    'app.components.page-queries.m83': 'Use selected cache as default schema name',
+    'app.components.page-queries.m84': 'Wrong caches filter',
+    'app.components.page-queries.m85': 'No caches',
+    'app.components.page-queries.m86': 'Error: {{paragraph.error.message}}',
+    'app.components.page-queries.m87': 'Show more',
+    'app.components.page-queries.m88': 'Show query',
+    'app.components.page-queries.m89': 'Next',
+    'app.components.page-queries.m90': 'Queries',
+    'app.components.page-queries.m91': 'With query notebook you can',
+    'app.components.page-queries.m92': 'Create any number of queries',
+    'app.components.page-queries.m93': 'Execute and explain SQL queries',
+    'app.components.page-queries.m94': 'Execute scan queries',
+    'app.components.page-queries.m95': 'View data in tabular form and as charts',
+    'app.components.page-queries.m96': 'Examples:',
+    // app/components/page-queries/Notebook.service.js
+    'app.components.page-queries.m97': 'Are you sure you want to remove notebook: "${notebook.name}"?',
+    // app/components/page-queries/Notebook.data.js
+    'app.components.page-queries.m98': 'SQL demo',
+    'app.components.page-queries.m99': 'Query with refresh rate',
+    'app.components.page-queries.m100': 'Simple query',
+    'app.components.page-queries.m101': 'Query with aggregates',
+    'app.components.page-queries.m102': 'Failed to load notebook.',
+    'app.components.page-queries.m103': 'Removing "${notebook.name}" notebook is not supported.',
+    // app/components/page-queries/index.js
+    'app.components.page-queries.m104': 'Query notebook',
+    'app.components.page-queries.m105': 'SQL demo',
+    // app/components/page-queries/controller.js
+    'app.components.page-queries.m106': 'Internal cluster error',
+    'app.components.page-queries.m107': 'Unlimited',
+    'app.components.page-queries.m108': 'Demo grid is starting. Please wait...',
+    'app.components.page-queries.m109': 'Loading query notebook screen...',
+    'app.components.page-queries.m110': 'seconds',
+    'app.components.page-queries.m111': 's',
+    'app.components.page-queries.m112': 'minutes',
+    'app.components.page-queries.m113': 'm',
+    'app.components.page-queries.m114': 'hours',
+    'app.components.page-queries.m115': 'h',
+    'app.components.page-queries.m116': 'Leave Queries',
+    'app.components.page-queries.m117': 'Query ${sz === 0 ? "" : sz}',
+    'app.components.page-queries.m118': 'Scan ${sz === 0 ? "" : sz}',
+    'app.components.page-queries.m119': 'Are you sure you want to remove query: "${paragraph.name}"?',
+    'app.components.page-queries.m120': 'Waiting for server response',
+    'app.components.page-queries.m121': 'Input text to ${action}',
+    'app.components.page-queries.m122': 'Waiting for server response',
+    'app.components.page-queries.m123': 'Select cache to export scan results',
+    'app.components.page-queries.m124': 'SCAN query',
+    'app.components.page-queries.m125': 'SCAN query for cache: <b>${maskCacheName(paragraph.queryArgs.cacheName, true)}</b>',
+    'app.components.page-queries.m126': 'SCAN query for cache: <b>${maskCacheName(paragraph.queryArgs.cacheName, true)}</b> with filter: <b>${filter}</b>',
+    'app.components.page-queries.m127': 'Explain query',
+    'app.components.page-queries.m128': 'SQL query',
+    'app.components.page-queries.m129': 'Duration: ${$filter(\'duration\')(paragraph.duration)}.',
+    'app.components.page-queries.m130': 'Node ID8: ${_.id8(paragraph.resNodeId)}',
+    'app.components.page-queries.m131': 'Error details',
+
+    // app/components/page-queries/services/queries-navbar.js
+    'app.components.page-queries.services.queries-navbar.m1': 'Queries',
+    'app.components.page-queries.services.queries-navbar.m2': 'Create new notebook',
+
+    // app/components/page-queries/services/create-query-dialog/template.pug
+    'app.components.page-queries.services.create-query-dialog.m1': 'New query notebook',
+    'app.components.page-queries.services.create-query-dialog.m2': 'Name:&nbsp;',
+    'app.components.page-queries.services.create-query-dialog.m3': 'Cancel',
+    'app.components.page-queries.services.create-query-dialog.m4': 'Create',
+
+    // app/components/page-profile/controller.js
+    'app.components.page-profile.m1': 'Are you sure you want to change security token?',
+    'app.components.page-profile.m2': 'Profile saved.',
+    'app.components.page-profile.m3': 'Failed to save profile: ',
+    // app/components/page-profile/index.js
+    'app.components.page-profile.m4': 'User profile',
+    // app/components/page-profile/template.pug
+    'app.components.page-profile.m5': 'User profile',
+    'app.components.page-profile.m6': 'First name:',
+    'app.components.page-profile.m7': 'Input first name',
+    'app.components.page-profile.m8': 'Last name:',
+    'app.components.page-profile.m9': 'Input last name',
+    'app.components.page-profile.m10': 'Email:',
+    'app.components.page-profile.m11': 'Input email',
+    'app.components.page-profile.m12': 'Phone:',
+    'app.components.page-profile.m13': 'Input phone (ex.: +15417543010)',
+    'app.components.page-profile.m14': 'Country:',
+    'app.components.page-profile.m15': 'Choose your country',
+    'app.components.page-profile.m16': 'Company:',
+    'app.components.page-profile.m17': 'Input company name',
+    'app.components.page-profile.m18': 'Cancel security token changing...',
+    'app.components.page-profile.m19': 'Show security token...',
+    'app.components.page-profile.m20': 'Security token:',
+    'app.components.page-profile.m21': 'No security token. Regenerate please.',
+    'app.components.page-profile.m22': 'Generate random security token',
+    'app.components.page-profile.m23': 'Copy security token to clipboard',
+    'app.components.page-profile.m24': 'The security token is used for authorization of web agent',
+    'app.components.page-profile.m25': 'Cancel password changing...',
+    'app.components.page-profile.m26': 'Change password...',
+    'app.components.page-profile.m27': 'New password:',
+    'app.components.page-profile.m28': 'New password',
+    'app.components.page-profile.m29': 'Confirm password:',
+    'app.components.page-profile.m30': 'Confirm new password',
+    'app.components.page-profile.m31': 'Cancel',
+    'app.components.page-profile.m32': 'Save Changes',
+
+    // app/modules/navbar/userbar.directive.js
+    'app/modules/navbar/userbar.m1': 'Profile',
+    'app/modules/navbar/userbar.m2': 'Getting started',
+    'app/modules/navbar/userbar.m3': 'Admin panel',
+    'app/modules/navbar/userbar.m4': 'Log out',
+
+    // app/components/page-forgot-password/run.js
+    'app.components.page-forgot-password.m1': 'Forgot Password',
+    // app/components/page-forgot-password/template.pug
+    'app.components.page-forgot-password.m2': 'Forgot password?',
+    'app.components.page-forgot-password.m3': 'Enter the email address for your account & we\'ll email you a link to reset your password.',
+    'app.components.page-forgot-password.m4': 'Email:',
+    'app.components.page-forgot-password.m5': 'Input email',
+    'app.components.page-forgot-password.m6': 'Back to sign in',
+    'app.components.page-forgot-password.m7': 'Send it to me',
+
+    // app/components/page-landing/template.pug
+    'app.components.page-landing.m1': 'Sign In',
+    'app.components.page-landing.m2': 'Web Console',
+    'app.components.page-landing.m3': 'An Interactive Configuration Wizard and Management Tool for Apache™ Ignite®',
+    'app.components.page-landing.m4': 'It provides an interactive configuration wizard which helps you create and download configuration files and code snippets for your Apache Ignite projects. Additionally, the tool allows you to automatically load SQL metadata from any RDBMS, run SQL queries on your in-memory cache, and view execution plans, in-memory schema, and streaming charts.',
+    'app.components.page-landing.m5': 'Sign Up',
+    'app.components.page-landing.m6': 'The Web Console allows you to:',
+    'app.components.page-landing.m7': 'Configure Apache Ignite clusters and caches',
+    'app.components.page-landing.m8': 'The Web Console configuration wizard takes you through a step-by-step process that helps you define all the required configuration parameters. The system then generates a ready-to-use project with all the required config files.',
+    'app.components.page-landing.m9': 'Run free-form SQL queries on #[br] Apache Ignite caches',
+    'app.components.page-landing.m10': 'By connecting the Web Console to your Apache Ignite cluster, you can execute SQL queries on your in-memory cache. You can also view the execution plan, in-memory schema, and streaming charts for your cluster.',
+    'app.components.page-landing.m11': 'Import database schemas from #[br] virtually any RDBMS',
+    'app.components.page-landing.m12': 'To speed the creation of your configuration files, the Web Console allows you to automatically import the database schema from virtually any RDBMS including Oracle, SAP, MySQL, PostgreSQL, and many more.',
+    'app.components.page-landing.m13': 'Manage the Web Console users',
+    'app.components.page-landing.m14': 'The Web Console allows you to have accounts with different roles.',
+    'app.components.page-landing.m15': 'Get Started',
+
+    // app/components/page-signup/template.pug
+    'app.components.page-signup.m1': 'Don\'t Have An Account?',
+    'app.components.page-signup.m2': 'Email:',
+    'app.components.page-signup.m3': 'Input email',
+    'app.components.page-signup.m4': 'Password:',
+    'app.components.page-signup.m5': 'Input password',
+    'app.components.page-signup.m6': 'Confirm:',
+    'app.components.page-signup.m7': 'Confirm password',
+    'app.components.page-signup.m8': 'First name:',
+    'app.components.page-signup.m9': 'Input first name',
+    'app.components.page-signup.m10': 'Last name:',
+    'app.components.page-signup.m11': 'Input last name',
+    'app.components.page-signup.m12': 'Phone:',
+    'app.components.page-signup.m13': 'Input phone (ex.: +15417543010)',
+    'app.components.page-signup.m14': 'Country:',
+    'app.components.page-signup.m15': 'Choose your country',
+    'app.components.page-signup.m16': 'Company:',
+    'app.components.page-signup.m17': 'Input company name',
+    'app.components.page-signup.m18': 'Sign Up',
+    'app.components.page-signup.m19': 'Already have an account? #[a(ui-sref=\'signin\') Sign in here]',
+
+    // app/components/password-visibility/toggle-button.component.js
+    'app.components.password-visibility.m1': 'Hide password',
+    'app.components.password-visibility.m2': 'Show password'
 };

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/filters/duration.filter.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/filters/duration.filter.js b/modules/web-console/frontend/app/filters/duration.filter.js
index 810cc4d..0ce4226 100644
--- a/modules/web-console/frontend/app/filters/duration.filter.js
+++ b/modules/web-console/frontend/app/filters/duration.filter.js
@@ -18,11 +18,15 @@
 export default () => {
     /**
      * @param {number} t Time in ms.
+     * @param {string} dflt Default value.
      */
-    const filter = (t) => {
+    const filter = (t, dflt = '0') => {
         if (t === 9223372036854775807)
             return 'Infinite';
 
+        if (t <= 0)
+            return dflt;
+
         const a = (i, suffix) => i && i !== '00' ? i + suffix + ' ' : '';
 
         const cd = 24 * 60 * 60 * 1000;

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/agent/AgentManager.service.js b/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
index aeb5f2b..8dbab0c 100644
--- a/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
+++ b/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
@@ -34,7 +34,7 @@ import {ClusterSecretsManager} from './types/ClusterSecretsManager';
 import ClusterLoginService from './components/cluster-login/service';
 
 const State = {
-    DISCONNECTED: 'DISCONNECTED',
+    INIT: 'INIT',
     AGENT_DISCONNECTED: 'AGENT_DISCONNECTED',
     CLUSTER_DISCONNECTED: 'CLUSTER_DISCONNECTED',
     CONNECTED: 'CONNECTED'
@@ -59,10 +59,9 @@ const SuccessStatus = {
 
 class ConnectionState {
     constructor(cluster) {
-        this.agents = [];
         this.cluster = cluster;
         this.clusters = [];
-        this.state = State.DISCONNECTED;
+        this.state = State.INIT;
     }
 
     updateCluster(cluster) {
@@ -103,13 +102,11 @@ class ConnectionState {
     }
 
     disconnect() {
-        this.agents = [];
-
         if (this.cluster)
             this.cluster.disconnect = true;
 
         this.clusters = [];
-        this.state = State.DISCONNECTED;
+        this.state = State.AGENT_DISCONNECTED;
     }
 }
 
@@ -385,7 +382,11 @@ export default class AgentManager {
             }
         });
 
-        this.$transitions.onExit({}, () => this.stopWatch());
+        const stopWatchUnsubscribe = this.$transitions.onExit({}, () => {
+            this.stopWatch();
+
+            stopWatchUnsubscribe();
+        });
 
         return this.awaitCluster();
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/modules/user/User.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/User.service.js b/modules/web-console/frontend/app/modules/user/User.service.js
index 3fdb9b9..3515c1b 100644
--- a/modules/web-console/frontend/app/modules/user/User.service.js
+++ b/modules/web-console/frontend/app/modules/user/User.service.js
@@ -15,6 +15,8 @@
  * limitations under the License.
  */
 
+import {ReplaySubject} from 'rxjs/ReplaySubject';
+
 /**
  * @typedef User
  * @prop {string} _id
@@ -40,7 +42,10 @@ export default function User($q, $injector, $root, $state, $http) {
     /** @type {ng.IPromise<User>} */
     let user;
 
+    const current$ = new ReplaySubject(1);
+
     return {
+        current$,
         /**
          * @returns {ng.IPromise<User>}
          */
@@ -51,6 +56,8 @@ export default function User($q, $injector, $root, $state, $http) {
 
                     $root.$broadcast('user', $root.user);
 
+                    current$.next(data);
+
                     return $root.user;
                 })
                 .catch(({data}) => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/modules/user/user.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/user.module.js b/modules/web-console/frontend/app/modules/user/user.module.js
index 9591a98..3e3068f 100644
--- a/modules/web-console/frontend/app/modules/user/user.module.js
+++ b/modules/web-console/frontend/app/modules/user/user.module.js
@@ -35,7 +35,7 @@ function sessionRecoverer($injector, $q) {
 
                 const stateName = $injector.get('$uiRouterGlobals').current.name;
 
-                if (!_.includes(['', 'signin'], stateName))
+                if (!_.includes(['', 'signin', 'terms', '403', '404'], stateName))
                     $injector.get('$state').go('signin');
             }
 
@@ -76,25 +76,28 @@ function run($root, $transitions, AclService, User, Activities) {
 
     $transitions.onBefore({}, (trans) => {
         const $state = trans.router.stateService;
-        const {name, permission} = trans.to();
+        const {permission} = trans.to();
 
         if (_.isEmpty(permission))
             return;
 
         return trans.injector().get('User').read()
             .then(() => {
-                if (AclService.can(permission)) {
-                    Activities.post({action: $state.href(name, trans.params('to'))});
-
-                    return;
-                }
-
-                return $state.target(trans.to().failState || '403');
+                if (!AclService.can(permission))
+                    throw new Error('Illegal access error');
             })
             .catch(() => {
                 return $state.target(trans.to().failState || '403');
             });
     });
+
+    $transitions.onFinish({}, (trans) => {
+        const $state = trans.router.stateService;
+        const {name, permission} = trans.to();
+
+        if (AclService.can(permission))
+            Activities.post({action: $state.href(name, trans.params('to'))});
+    });
 }
 
 run.$inject = ['$rootScope', '$transitions', 'AclService', 'User', 'IgniteActivitiesData'];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/primitives/tooltip/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/tooltip/index.scss b/modules/web-console/frontend/app/primitives/tooltip/index.scss
index a6cd79f..71076e2 100644
--- a/modules/web-console/frontend/app/primitives/tooltip/index.scss
+++ b/modules/web-console/frontend/app/primitives/tooltip/index.scss
@@ -39,4 +39,4 @@
         border-color: #f34718;
         color: white;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/services/FormUtils.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/services/FormUtils.service.js b/modules/web-console/frontend/app/services/FormUtils.service.js
index c8ce4b0..aa46381 100644
--- a/modules/web-console/frontend/app/services/FormUtils.service.js
+++ b/modules/web-console/frontend/app/services/FormUtils.service.js
@@ -339,7 +339,7 @@ export default function service($window, Focus, $rootScope) {
                 return;
 
             const walk = (m) => {
-                if (!m.$error[e])
+                if (!m || !m.$error[e])
                     return;
 
                 if (m.$error[e] === true)

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/app/services/exceptionHandler.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/services/exceptionHandler.js b/modules/web-console/frontend/app/services/exceptionHandler.js
index c6a09c3..6b5f4e4 100644
--- a/modules/web-console/frontend/app/services/exceptionHandler.js
+++ b/modules/web-console/frontend/app/services/exceptionHandler.js
@@ -25,6 +25,10 @@ export function $exceptionHandler($log) {
         if (exception instanceof CancellationError)
             return;
 
+        // From ui-grid
+        if (exception === 'Possibly unhandled rejection: canceled')
+            return;
+
         $log.error(exception, cause);
     };
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/package.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/package.json b/modules/web-console/frontend/package.json
index fce79ef..2260f75 100644
--- a/modules/web-console/frontend/package.json
+++ b/modules/web-console/frontend/package.json
@@ -10,7 +10,7 @@
     "build": "webpack --config ./webpack/webpack.prod.js",
     "test": "karma start ./test/karma.conf.js",
     "test-watch": "npm test -- --no-single-run",
-    "eslint": "eslint --format node_modules/eslint-friendly-formatter app/ -- --eff-by-issue"
+    "eslint": "eslint --ignore-pattern node_modules/ --format node_modules/eslint-formatter-friendly . -- --eff-by-issue"
   },
   "license": "Apache-2.0",
   "keywords": [
@@ -28,7 +28,6 @@
   ],
   "dependencies": {
     "@babel/plugin-transform-parameters": "7.0.0",
-    "@types/angular-translate": "2.16.0",
     "@uirouter/angularjs": "1.0.20",
     "@uirouter/core": "5.0.19",
     "@uirouter/rx": "0.4.1",
@@ -85,6 +84,7 @@
     "@types/angular-animate": "1.5.10",
     "@types/angular-mocks": "1.5.12",
     "@types/angular-strap": "2.3.1",
+    "@types/angular-translate": "2.16.0",
     "@types/chai": "4.1.4",
     "@types/copy-webpack-plugin": "4.4.2",
     "@types/karma": "1.7.4",
@@ -108,7 +108,6 @@
     "eslint": "4.19.1",
     "eslint-formatter-friendly": "6.0.0",
     "eslint-loader": "2.1.0",
-    "eslint-plugin-babel": "5.2.0",
     "eslint-plugin-typescript": "0.12.0",
     "expose-loader": "0.7.5",
     "file-loader": "1.1.11",

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/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 ded958e..e68dedf 100644
--- a/modules/web-console/frontend/public/stylesheets/_bootstrap-variables.scss
+++ b/modules/web-console/frontend/public/stylesheets/_bootstrap-variables.scss
@@ -726,7 +726,7 @@ $list-group-link-heading-color: #333 !default;
 
 $panel-bg:                    #fff !default;
 $panel-body-padding:          15px !default;
-$panel-heading-padding:       10px 15px !default;
+$panel-heading-padding:       5px 10px !default;
 $panel-footer-padding:        $panel-heading-padding !default;
 $panel-border-radius:         $border-radius-base !default;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ec9ee43/modules/web-console/frontend/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/style.scss b/modules/web-console/frontend/public/stylesheets/style.scss
index a00a585..f9c9c4a 100644
--- a/modules/web-console/frontend/public/stylesheets/style.scss
+++ b/modules/web-console/frontend/public/stylesheets/style.scss
@@ -593,7 +593,6 @@ button.form-control {
 }
 
 .theme-line .panel-heading {
-    padding: 5px 10px;
     margin: 0;
     cursor: pointer;
     font-size: $font-size-large;