Repository: ignite
Updated Branches:
  refs/heads/ignite-6083 bea574b93 -> b2fe867f8


IGNITE-8334 Web Console: Added ability to show/hide password field value.


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

Branch: refs/heads/ignite-6083
Commit: e0d1752a103e4ebfb6378c652f7966eab5a58d57
Parents: ecea655
Author: Ilya Borisov <[email protected]>
Authored: Mon Apr 23 15:12:18 2018 +0700
Committer: Alexey Kuznetsov <[email protected]>
Committed: Mon Apr 23 15:12:18 2018 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/app/app.js         |   4 +-
 .../app/components/password-visibility/index.js |  26 +++
 .../password-visibility/index.spec.js           |  65 +++++++
 .../password-visibility/root.directive.js       |  49 ++++++
 .../components/password-visibility/style.scss   |  50 ++++++
 .../toggle-button.component.js                  |  49 ++++++
 .../frontend/app/directives/match.directive.js  |  32 +++-
 .../app/directives/match.directive.spec.js      |  81 +++++++++
 .../generator/Docker.service.spec.js            |   2 +-
 .../app/primitives/form-field/index.scss        |  26 +++
 .../app/primitives/form-field/password.pug      |  12 +-
 modules/web-console/frontend/package-lock.json  | 171 ++++++++++---------
 .../frontend/public/images/icons/eyeClosed.svg  |   6 +
 .../frontend/public/images/icons/eyeOpened.svg  |   7 +
 .../frontend/public/images/icons/index.js       |   3 +-
 15 files changed, 492 insertions(+), 91 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.js 
b/modules/web-console/frontend/app/app.js
index 692acc5..c6720bc 100644
--- a/modules/web-console/frontend/app/app.js
+++ b/modules/web-console/frontend/app/app.js
@@ -138,6 +138,7 @@ import clusterSelector from './components/cluster-selector';
 import connectedClusters from './components/connected-clusters';
 import pageSignIn from './components/page-signin';
 import pageLanding from './components/page-landing';
+import passwordVisibility from './components/password-visibility';
 
 import pageProfile from './components/page-profile';
 import pagePasswordChanged from './components/page-password-changed';
@@ -239,6 +240,7 @@ angular.module('ignite-console', [
     uiAceJava.name,
     uiAceSpring.name,
     breadcrumbs.name,
+    passwordVisibility.name,
     // Ignite modules.
     IgniteModules.name
 ])
@@ -250,7 +252,7 @@ angular.module('ignite-console', [
 .directive(...igniteCopyToClipboard)
 .directive(...igniteHideOnStateChange)
 .directive(...igniteInformation)
-.directive(...igniteMatch)
+.directive('igniteMatch', igniteMatch)
 .directive(...igniteOnClickFocus)
 .directive(...igniteOnEnter)
 .directive(...igniteOnEnterFocusMove)

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/components/password-visibility/index.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/components/password-visibility/index.js 
b/modules/web-console/frontend/app/components/password-visibility/index.js
new file mode 100644
index 0000000..d735869
--- /dev/null
+++ b/modules/web-console/frontend/app/components/password-visibility/index.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import angular from 'angular';
+import './style.scss';
+import {directive as visibilityRoot} from './root.directive';
+import {component as toggleButton} from './toggle-button.component';
+
+export default angular
+    .module('ignite-console.passwordVisibility', [])
+    .directive('passwordVisibilityRoot', visibilityRoot)
+    .component('passwordVisibilityToggleButton', toggleButton);

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/components/password-visibility/index.spec.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/components/password-visibility/index.spec.js 
b/modules/web-console/frontend/app/components/password-visibility/index.spec.js
new file mode 100644
index 0000000..236e497
--- /dev/null
+++ 
b/modules/web-console/frontend/app/components/password-visibility/index.spec.js
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'mocha';
+import {assert} from 'chai';
+import angular from 'angular';
+import module from './index';
+
+const PASSWORD_VISIBLE_CLASS = 'password-visibility__password-visible';
+
+suite('password-visibility', () => {
+    /** @type {ng.IScope} */
+    let $scope;
+    /** @type {ng.ICompileService} */
+    let $compile;
+
+    angular.module('test', [module.name]);
+
+    setup(() => {
+        angular.module('test', [module.name]);
+        angular.mock.module('test');
+        angular.mock.inject((_$rootScope_, _$compile_) => {
+            $compile = _$compile_;
+            $scope = _$rootScope_.$new();
+        });
+    });
+
+    test('Visibility toggle', () => {
+        const el = angular.element(`
+            <div password-visibility-root 
on-password-visibility-toggle='visible = $event'>
+                
<password-visibility-toggle-button></password-visibility-toggle-button>
+            </div>
+        `);
+        $compile(el)($scope);
+        const toggleButton = el.find('password-visibility-toggle-button 
button');
+        $scope.$digest();
+
+        assert.isFalse(el.hasClass(PASSWORD_VISIBLE_CLASS), 'Password is 
hidden by default');
+
+        toggleButton.click();
+        $scope.$digest();
+
+        assert.isTrue(el.hasClass(PASSWORD_VISIBLE_CLASS), 'Password is 
visible after click on toggle button');
+        assert.equal(true, $scope.visible, 'Event emits current visibility 
value');
+
+        toggleButton.click();
+        $scope.$digest();
+
+        assert.isFalse(el.hasClass(PASSWORD_VISIBLE_CLASS), 'Password is 
hidden again after two clicks on button');
+    });
+});

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/components/password-visibility/root.directive.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/components/password-visibility/root.directive.js
 
b/modules/web-console/frontend/app/components/password-visibility/root.directive.js
new file mode 100644
index 0000000..a041398
--- /dev/null
+++ 
b/modules/web-console/frontend/app/components/password-visibility/root.directive.js
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const PASSWORD_VISIBLE_CLASS = 'password-visibility__password-visible';
+
+export class PasswordVisibilityRoot {
+    /** @type {ng.ICompiledExpression} */
+    onPasswordVisibilityToggle;
+
+    isVisible = false;
+    static $inject = ['$element'];
+
+    /**
+     * @param {JQLite} $element
+     */
+    constructor($element) {
+        this.$element = $element;
+    }
+    toggleVisibility() {
+        this.isVisible = !this.isVisible;
+        this.$element.toggleClass(PASSWORD_VISIBLE_CLASS, this.isVisible);
+        if (this.onPasswordVisibilityToggle) 
this.onPasswordVisibilityToggle({$event: this.isVisible});
+    }
+}
+
+export function directive() {
+    return {
+        restrict: 'A',
+        scope: false,
+        controller: PasswordVisibilityRoot,
+        bindToController: {
+            onPasswordVisibilityToggle: '&?'
+        }
+    };
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/components/password-visibility/style.scss
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/components/password-visibility/style.scss 
b/modules/web-console/frontend/app/components/password-visibility/style.scss
new file mode 100644
index 0000000..6f5130b
--- /dev/null
+++ b/modules/web-console/frontend/app/components/password-visibility/style.scss
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+[password-visibility-root] {
+    &:not(.password-visibility__password-visible) {
+        .password-visibility__icon-visible,
+        .password-visibility__password-visible {
+            display: none;
+        }        
+    }
+
+    &.password-visibility__password-visible {
+        .password-visibility__icon-hidden,
+        .password-visibility__password-hidden {
+            display: none;
+        }
+    }
+}
+
+password-visibility-toggle-button {
+    display: inline-block;
+    width: 36px;
+
+    button {
+        display: inline-flex;
+        align-items: center;
+        justify-content: center;
+        width: 100%;
+        height: 100%;
+        background: none;
+        border: none;
+        outline: none;
+        padding: 0 !important;
+        margin: 0 !important;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/components/password-visibility/toggle-button.component.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/components/password-visibility/toggle-button.component.js
 
b/modules/web-console/frontend/app/components/password-visibility/toggle-button.component.js
new file mode 100644
index 0000000..2e16201
--- /dev/null
+++ 
b/modules/web-console/frontend/app/components/password-visibility/toggle-button.component.js
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {PasswordVisibilityRoot} from './root.directive';
+
+class Controller {
+    /** @type {PasswordVisibilityRoot} */
+    visibilityRoot;
+
+    toggleVisibility() {
+        this.visibilityRoot.toggleVisibility();
+    }
+    get isVisible() {
+        return this.visibilityRoot.isVisible;
+    }
+}
+
+export const component = {
+    template: `
+        <button
+            type='button'
+            ng-click='$ctrl.toggleVisibility()'
+            bs-tooltip=''
+            data-title='{{ $ctrl.isVisible ? "Hide password" : "Show password" 
}}'
+            data-placement='top'
+        >
+            <svg ignite-icon='eyeOpened' 
class='password-visibility__icon-visible'></svg>
+            <svg ignite-icon='eyeClosed' 
class='password-visibility__icon-hidden'></svg>
+        </button>
+    `,
+    require: {
+        visibilityRoot: '^passwordVisibilityRoot'
+    },
+    controller: Controller
+};

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/directives/match.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/directives/match.directive.js 
b/modules/web-console/frontend/app/directives/match.directive.js
index 3a45f6d..940ca08 100644
--- a/modules/web-console/frontend/app/directives/match.directive.js
+++ b/modules/web-console/frontend/app/directives/match.directive.js
@@ -16,12 +16,32 @@
  */
 
 // Directive to enable validation to match specified value.
-export default ['igniteMatch', ['$parse', ($parse) => {
+export default function() {
     return {
-        require: 'ngModel',
-        link(scope, elem, attrs, ctrl) {
-            scope.$watch(() => $parse(attrs.igniteMatch)(scope) === 
ctrl.$modelValue,
-                (currentValue) => ctrl.$setValidity('mismatch', currentValue));
+        require: {
+            ngModel: 'ngModel'
+        },
+        scope: false,
+        bindToController: {
+            igniteMatch: '<'
+        },
+        controller: class {
+            /** @type {ng.INgModelController} */
+            ngModel;
+            /** @type {string} */
+            igniteMatch;
+
+            $postLink() {
+                this.ngModel.$overrideModelOptions({allowInvalid: true});
+                this.ngModel.$validators.mismatch = (value) => value === 
this.igniteMatch;
+            }
+
+            /**
+             * @param {{igniteMatch: ng.IChangesObject<string>}} changes
+             */
+            $onChanges(changes) {
+                if ('igniteMatch' in changes) this.ngModel.$validate();
+            }
         }
     };
-}]];
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/directives/match.directive.spec.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/directives/match.directive.spec.js 
b/modules/web-console/frontend/app/directives/match.directive.spec.js
new file mode 100644
index 0000000..2a00b03
--- /dev/null
+++ b/modules/web-console/frontend/app/directives/match.directive.spec.js
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'mocha';
+import {assert} from 'chai';
+import angular from 'angular';
+import directive from './match.directive';
+
+/**
+ * @param {HTMLInputElement} el
+ * @returns {ng.INgModelController}
+ */
+const ngModel = (el) => angular.element(el).data().$ngModelController;
+
+suite('ignite-match', () => {
+    /** @type {ng.IScope} */
+    let $scope;
+    /** @type {ng.ICompileService} */
+    let $compile;
+
+    setup(() => {
+        angular.module('test', []).directive('igniteMatch', directive);
+        angular.mock.module('test');
+        angular.mock.inject((_$rootScope_, _$compile_) => {
+            $compile = _$compile_;
+            $scope = _$rootScope_.$new();
+        });
+    });
+
+    test('Matching', () => {
+        const el = angular.element(`
+            <input type="password" ng-model="data.master"/>
+            <input type="password" ng-model="data.slave" 
ignite-match="data.master"/>
+        `);
+
+        const setValue = (el, value) => {
+            ngModel(el).$setViewValue(value, 'input');
+            $scope.$digest();
+        };
+
+        $scope.data = {};
+        $compile(el)($scope);
+        $scope.$digest();
+
+        const [master, , slave] = el;
+
+        setValue(slave, '123');
+        $scope.$digest();
+
+        assert.isTrue(
+            slave.classList.contains('ng-invalid-mismatch'),
+            `Invalidates if slave input changes value and it doesn't match 
master value`
+        );
+        assert.equal(
+            $scope.data.slave,
+            '123',
+            'Allows invalid value into model'
+        );
+
+        setValue(master, '123');
+
+        assert.isFalse(
+            slave.classList.contains('ng-invalid-mismatch'),
+            `Runs validation on master value change`
+        );
+    });
+});

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.spec.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.spec.js
 
b/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.spec.js
index becc359..0ecada7 100644
--- 
a/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.spec.js
+++ 
b/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.spec.js
@@ -19,7 +19,7 @@ import DockerGenerator from './Docker.service';
 import {assert} from 'chai';
 import {outdent} from 'outdent/lib';
 
-suite.only('Dockerfile generator', () => {
+suite('Dockerfile generator', () => {
     const generator = new DockerGenerator();
 
     test('Target 2.0', () => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/primitives/form-field/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/form-field/index.scss 
b/modules/web-console/frontend/app/primitives/form-field/index.scss
index 1035ade..800daa8 100644
--- a/modules/web-console/frontend/app/primitives/form-field/index.scss
+++ b/modules/web-console/frontend/app/primitives/form-field/index.scss
@@ -242,6 +242,8 @@
         }
 
         // Added right offset to appearance of input for invalid password
+        & > input[type='email'].ng-invalid.ng-touched,
+        & > input[type='text'].ng-invalid.ng-touched,
         & > input[type='password'].ng-invalid.ng-touched {
             padding-right: 36px;
         }
@@ -328,3 +330,27 @@
         }
     }
 }
+
+.form-field__password {
+    // Validation error notification will overlap with visibility button if 
it's not moved more to the left
+    input[type='password'].ng-invalid.ng-touched,
+    input[type='password'].ng-invalid.ng-touched + input {
+        padding-right: 62px;
+    }
+
+    // Extra space for visibility button
+    input {
+        padding-right: 36px;
+    }
+
+    // Distance between error notification and visibility button
+    .form-field__errors {
+        right: 26px;
+    }
+
+    password-visibility-toggle-button {
+        position: absolute;
+        right: 0;
+        height: 36px;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/app/primitives/form-field/password.pug
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/primitives/form-field/password.pug 
b/modules/web-console/frontend/app/primitives/form-field/password.pug
index ba38cce..40e1aa9 100644
--- a/modules/web-console/frontend/app/primitives/form-field/password.pug
+++ b/modules/web-console/frontend/app/primitives/form-field/password.pug
@@ -17,13 +17,23 @@
 mixin form-field__password({ label, model, name, disabled, required, 
placeholder, tip })
     -var errLbl = label.substring(0, label.length - 1)
 
-    .form-field
+    .form-field.form-field__password(
+        password-visibility-root
+        on-password-visibility-toggle=`${form}[${name}].$setTouched()`
+    )
         +form-field__label({ label, name, required })
             +form-field__tooltip({ title: tip, options: tipOpts })
 
         .form-field__control
             - attributes.type='password'
+            - attributes.class = 'password-visibility__password-hidden'
             +form-field__input({ name, model, disabled, required, placeholder 
})(attributes=attributes)
+            - attributes.class = 'password-visibility__password-visible'
+            - attributes.type='text'
+            - attributes.autocomplete = 'off'
+            +form-field__input({ name: name + `+"Text"`, model, disabled, 
required, placeholder })(attributes=attributes)
+
+            password-visibility-toggle-button
 
         .form-field__errors(
             ng-messages=`(${form}[${name}].$dirty || ${form}[${name}].$touched 
|| ${form}[${name}].$submitted) && ${form}[${name}].$invalid ? 
${form}[${name}].$error : {}`

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/package-lock.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/package-lock.json 
b/modules/web-console/frontend/package-lock.json
index 1fec909..c966cb7 100644
--- a/modules/web-console/frontend/package-lock.json
+++ b/modules/web-console/frontend/package-lock.json
@@ -71,9 +71,9 @@
       }
     },
     "@types/chai": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.2.tgz";,
-      "integrity": 
"sha512-D8uQwKYUw2KESkorZ27ykzXgvkDJYXVEihGklgfp5I4HUP8D6IxtcdLTMB1emjQiWzV7WZ5ihm1cxIzVwjoleQ==",
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.3.tgz";,
+      "integrity": 
"sha512-f5dXGzOJycyzSMdaXVhiBhauL4dYydXwVpavfQ1mVCaGjR56a9QfklXObUxlIY9bGTmCPHEEZ04I16BZ/8w5ww==",
       "dev": true
     },
     "@types/jquery": {
@@ -95,9 +95,9 @@
       "dev": true
     },
     "@types/node": {
-      "version": "9.6.5",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.5.tgz";,
-      "integrity": 
"sha512-NOLEgsT6UiDTjnWG5Hd2Mg25LRyz/oe8ql3wbjzgSFeRzRROhPmtlsvIrei4B46UjERF0td9SZ1ZXPLOdcrBHg==",
+      "version": "9.6.6",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.6.tgz";,
+      "integrity": 
"sha512-SJe0g5cZeGNDP5sD8mIX3scb+eq8LQQZ60FXiKZHipYSeEFZ5EKml+NNMiO76F74TY4PoMWlNxF/YRY40FOvZQ==",
       "dev": true
     },
     "@types/sinon": {
@@ -145,7 +145,7 @@
       "integrity": 
"sha512-NoGVTCumOsyFfuy3934f3ktiJi+wcXHJFxT47tby3iCpuo6M/WjFA9VqT5bYO+FE46i3R0N00RpJX75HxHKDaQ==",
       "dev": true,
       "requires": {
-        "@types/node": "9.6.5",
+        "@types/node": "9.6.6",
         "@types/tapable": "1.0.2",
         "@types/uglify-js": "3.0.2",
         "source-map": "0.6.1"
@@ -465,9 +465,9 @@
       "integrity": "sha1-ClsQZgGLQOcAuMbuNLDJf8MhlSs="
     },
     "angular-ui-grid": {
-      "version": "4.4.6",
-      "resolved": 
"https://registry.npmjs.org/angular-ui-grid/-/angular-ui-grid-4.4.6.tgz";,
-      "integrity": 
"sha512-0d14HDY4XeqFHI508thxeufiR0AlFoZQ8ihk0x8TRCQc+b9CCk1/F63W2zihirxF0cdOAqBCY2pVSM7vfZvXBQ==",
+      "version": "4.4.7",
+      "resolved": 
"https://registry.npmjs.org/angular-ui-grid/-/angular-ui-grid-4.4.7.tgz";,
+      "integrity": 
"sha512-z592OgLcVkyfGVMU2M0ymTPjBh/F+0/fAy/Yzj19Cs7wmuYcb13+iGFPskas27uDdxKv4mkJqmGeklyh5NxJEw==",
       "requires": {
         "angular": "1.6.6"
       }
@@ -3250,7 +3250,7 @@
         "cipher-base": "1.0.4",
         "inherits": "2.0.3",
         "md5.js": "1.3.4",
-        "ripemd160": "2.0.1",
+        "ripemd160": "2.0.2",
         "sha.js": "2.4.11"
       }
     },
@@ -3262,7 +3262,7 @@
         "cipher-base": "1.0.4",
         "create-hash": "1.2.0",
         "inherits": "2.0.3",
-        "ripemd160": "2.0.1",
+        "ripemd160": "2.0.2",
         "safe-buffer": "5.1.1",
         "sha.js": "2.4.11"
       }
@@ -3297,7 +3297,7 @@
         "create-hmac": "1.1.7",
         "diffie-hellman": "5.0.3",
         "inherits": "2.0.3",
-        "pbkdf2": "3.0.14",
+        "pbkdf2": "3.0.16",
         "public-encrypt": "4.0.2",
         "randombytes": "2.0.6",
         "randomfill": "1.0.4"
@@ -3972,9 +3972,9 @@
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
     },
     "ejs": {
-      "version": "2.5.8",
-      "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.8.tgz";,
-      "integrity": 
"sha512-QIDZL54fyV8MDcAsO91BMH1ft2qGGaHIJsJIA/+t+7uvXol1dm413fPcUgUb4k8F/9457rx4/KFE4XfDifrQxQ=="
+      "version": "2.5.9",
+      "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz";,
+      "integrity": 
"sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ=="
     },
     "electron-to-chromium": {
       "version": "1.3.42",
@@ -4402,9 +4402,9 @@
       "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
     },
     "eventemitter3": {
-      "version": "1.2.0",
-      "resolved": 
"https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz";,
-      "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg="
+      "version": "3.0.1",
+      "resolved": 
"https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.0.1.tgz";,
+      "integrity": 
"sha512-QOCPu979MMWX9XNlfRZoin+Wm+bK1SP7vv3NGUniYwuSJK/+cPA10blMaeRgzg31RvoSFk6FsCDVa4vNryBTGA=="
     },
     "events": {
       "version": "1.1.1",
@@ -4622,9 +4622,9 @@
       "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
     },
     "fast-glob": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.0.tgz";,
-      "integrity": 
"sha512-4F75PTznkNtSKs2pbhtBwRkw8sRwa7LfXx5XaQJOe4IQ6yTjceLDTwM5gj1s80R2t/5WeDC1gVfm3jLE+l39Tw==",
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.1.tgz";,
+      "integrity": 
"sha512-wSyW1TBK3ia5V+te0rGPXudeMHoUQW6O5Y9oATiaGhpENmEifPDlOdhpsnlj5HoG6ttIvGiY1DdCmI9X2xGMhg==",
       "dev": true,
       "requires": {
         "@mrmlnc/readdir-enhanced": "2.2.1",
@@ -5118,6 +5118,24 @@
         "readable-stream": "2.3.6"
       }
     },
+    "follow-redirects": {
+      "version": "1.4.1",
+      "resolved": 
"https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz";,
+      "integrity": 
"sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==",
+      "requires": {
+        "debug": "3.1.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz";,
+          "integrity": 
"sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
     "font-awesome": {
       "version": "4.7.0",
       "resolved": 
"https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz";,
@@ -5491,7 +5509,7 @@
       "requires": {
         "array-union": "1.0.2",
         "dir-glob": "2.0.0",
-        "fast-glob": "2.2.0",
+        "fast-glob": "2.2.1",
         "glob": "7.1.2",
         "ignore": "3.3.7",
         "pify": "3.0.0",
@@ -5842,7 +5860,7 @@
         "he": "1.1.1",
         "param-case": "2.1.1",
         "relateurl": "0.2.7",
-        "uglify-js": "3.3.21"
+        "uglify-js": "3.3.22"
       },
       "dependencies": {
         "commander": {
@@ -5856,9 +5874,9 @@
           "integrity": 
"sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
         },
         "uglify-js": {
-          "version": "3.3.21",
-          "resolved": 
"https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.21.tgz";,
-          "integrity": 
"sha512-uy82472lH8tshK3jS3c5IFb5MmNKd/5qyBd0ih8sM42L3jWvxnE339U9gZU1zufnLVs98Stib9twq8dLm2XYCA==",
+          "version": "3.3.22",
+          "resolved": 
"https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.22.tgz";,
+          "integrity": 
"sha512-tqw96rL6/BG+7LM5VItdhDjTQmL5zG/I0b2RqWytlgeHe2eydZHuBHdA9vuGpCDhH/ZskNGcqDhivoR2xt8RIw==",
           "requires": {
             "commander": "2.15.1",
             "source-map": "0.6.1"
@@ -6032,11 +6050,12 @@
       "integrity": 
"sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA=="
     },
     "http-proxy": {
-      "version": "1.16.2",
-      "resolved": 
"https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz";,
-      "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=",
+      "version": "1.17.0",
+      "resolved": 
"https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz";,
+      "integrity": 
"sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
       "requires": {
-        "eventemitter3": "1.2.0",
+        "eventemitter3": "3.0.1",
+        "follow-redirects": "1.4.1",
         "requires-port": "1.0.0"
       }
     },
@@ -6045,7 +6064,7 @@
       "resolved": 
"https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz";,
       "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=",
       "requires": {
-        "http-proxy": "1.16.2",
+        "http-proxy": "1.17.0",
         "is-glob": "3.1.0",
         "lodash": "4.17.5",
         "micromatch": "2.3.11"
@@ -6798,7 +6817,7 @@
         "babel-preset-es2015": "6.24.1",
         "babel-preset-stage-1": "6.24.1",
         "babel-register": "6.26.0",
-        "babylon": "7.0.0-beta.44",
+        "babylon": "7.0.0-beta.46",
         "colors": "1.1.2",
         "flow-parser": "0.70.0",
         "lodash": "4.17.5",
@@ -6812,9 +6831,9 @@
       },
       "dependencies": {
         "babylon": {
-          "version": "7.0.0-beta.44",
-          "resolved": 
"https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz";,
-          "integrity": 
"sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g=="
+          "version": "7.0.0-beta.46",
+          "resolved": 
"https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.46.tgz";,
+          "integrity": 
"sha512-WFJlg2WatdkXRFMpk7BN/Uzzkjkcjk+WaqnrSCpay+RYl4ypW9ZetZyT9kNt22IH/BQNst3M6PaaBn9IXsUNrg=="
         }
       }
     },
@@ -7036,7 +7055,7 @@
         "expand-braces": "0.1.2",
         "glob": "7.1.2",
         "graceful-fs": "4.1.11",
-        "http-proxy": "1.16.2",
+        "http-proxy": "1.17.0",
         "isbinaryfile": "3.0.2",
         "lodash": "4.17.5",
         "log4js": "2.5.3",
@@ -7882,7 +7901,7 @@
       "requires": {
         "commondir": "1.0.1",
         "deep-extend": "0.4.2",
-        "ejs": "2.5.8",
+        "ejs": "2.5.9",
         "glob": "7.1.2",
         "globby": "6.1.0",
         "mkdirp": "0.5.1",
@@ -8543,7 +8562,7 @@
         "stream-browserify": "2.0.1",
         "stream-http": "2.8.1",
         "string_decoder": "1.1.1",
-        "timers-browserify": "2.0.9",
+        "timers-browserify": "2.0.10",
         "tty-browserify": "0.0.0",
         "url": "0.11.0",
         "util": "0.10.3",
@@ -9136,7 +9155,7 @@
         "browserify-aes": "1.2.0",
         "create-hash": "1.2.0",
         "evp_bytestokey": "1.0.3",
-        "pbkdf2": "3.0.14"
+        "pbkdf2": "3.0.16"
       }
     },
     "parse-glob": {
@@ -9258,13 +9277,13 @@
       "dev": true
     },
     "pbkdf2": {
-      "version": "3.0.14",
-      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz";,
-      "integrity": 
"sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
+      "version": "3.0.16",
+      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz";,
+      "integrity": 
"sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==",
       "requires": {
         "create-hash": "1.2.0",
         "create-hmac": "1.1.7",
-        "ripemd160": "2.0.1",
+        "ripemd160": "2.0.2",
         "safe-buffer": "5.1.1",
         "sha.js": "2.4.11"
       }
@@ -9468,7 +9487,7 @@
         "caniuse-api": "1.6.1",
         "postcss": "5.2.18",
         "postcss-selector-parser": "2.2.3",
-        "vendors": "1.0.1"
+        "vendors": "1.0.2"
       }
     },
     "postcss-message-helpers": {
@@ -9874,9 +9893,9 @@
       }
     },
     "posthtml-rename-id": {
-      "version": "1.0.4",
-      "resolved": 
"https://registry.npmjs.org/posthtml-rename-id/-/posthtml-rename-id-1.0.4.tgz";,
-      "integrity": 
"sha512-bxsGN02JGqcihc9eztWu8Qlj2P/If9sY0ckYmEL+6hqrWRvwJw4RvnXSnlKmjS4yDBcT4cSpJdMy+xsSuHDvZw==",
+      "version": "1.0.5",
+      "resolved": 
"https://registry.npmjs.org/posthtml-rename-id/-/posthtml-rename-id-1.0.5.tgz";,
+      "integrity": 
"sha512-s1Zc2r8nxke55DCUbBE0EOUWqnt42BHIOl80GW20iNMCRZbkaPWRHTbSEVOmfng+Zl1F9wZL4LXVYDCzl6nYhw==",
       "requires": {
         "escape-string-regexp": "1.0.5"
       }
@@ -10916,22 +10935,12 @@
       }
     },
     "ripemd160": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz";,
-      "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz";,
+      "integrity": 
"sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
       "requires": {
-        "hash-base": "2.0.2",
+        "hash-base": "3.0.4",
         "inherits": "2.0.3"
-      },
-      "dependencies": {
-        "hash-base": {
-          "version": "2.0.2",
-          "resolved": 
"https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz";,
-          "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
-          "requires": {
-            "inherits": "2.0.3"
-          }
-        }
       }
     },
     "roboto-font": {
@@ -11765,7 +11774,7 @@
         "faye-websocket": "0.11.1",
         "inherits": "2.0.3",
         "json3": "3.3.2",
-        "url-parse": "1.3.0"
+        "url-parse": "1.4.0"
       },
       "dependencies": {
         "faye-websocket": {
@@ -12202,7 +12211,7 @@
         "micromatch": "3.1.0",
         "postcss": "5.2.18",
         "postcss-prefix-selector": "1.6.0",
-        "posthtml-rename-id": "1.0.4",
+        "posthtml-rename-id": "1.0.5",
         "posthtml-svg-mode": "1.0.2",
         "query-string": "4.3.4",
         "traverse": "0.6.6"
@@ -12533,9 +12542,9 @@
       "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8="
     },
     "timers-browserify": {
-      "version": "2.0.9",
-      "resolved": 
"https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.9.tgz";,
-      "integrity": 
"sha512-2DhyvVpCWwY7gk8UmKhYvgHQl9XTlO0Dg0/2UZcLgPnpulhdm2aGIlFy5rU5igmOCA51w6jPHqLRA4UH1YmhcA==",
+      "version": "2.0.10",
+      "resolved": 
"https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz";,
+      "integrity": 
"sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==",
       "requires": {
         "setimmediate": "1.0.5"
       }
@@ -12998,18 +13007,18 @@
       "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo="
     },
     "url-parse": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.3.0.tgz";,
-      "integrity": 
"sha512-zPvPA3T7P6M+0iNsgX+iAcAz4GshKrowtQBHHc/28tVsBc8jK7VRCNX+2GEcoE6zDB6XqXhcyiUWPVZY6C70Cg==",
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.0.tgz";,
+      "integrity": 
"sha512-ERuGxDiQ6Xw/agN4tuoCRbmwRuZP0cJ1lJxJubXr5Q/5cDa78+Dc4wfvtxzhzhkm5VvmW6Mf8EVj9SPGN4l8Lg==",
       "requires": {
-        "querystringify": "1.0.0",
+        "querystringify": "2.0.0",
         "requires-port": "1.0.0"
       },
       "dependencies": {
         "querystringify": {
-          "version": "1.0.0",
-          "resolved": 
"https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz";,
-          "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs="
+          "version": "2.0.0",
+          "resolved": 
"https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz";,
+          "integrity": 
"sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw=="
         }
       }
     },
@@ -13130,9 +13139,9 @@
       "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
     },
     "vendors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz";,
-      "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI="
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz";,
+      "integrity": 
"sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ=="
     },
     "verror": {
       "version": "1.10.0",
@@ -13663,9 +13672,9 @@
           }
         },
         "cliui": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz";,
-          "integrity": 
"sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz";,
+          "integrity": 
"sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
           "requires": {
             "string-width": "2.1.1",
             "strip-ansi": "4.0.0",
@@ -13763,7 +13772,7 @@
           "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz";,
           "integrity": 
"sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==",
           "requires": {
-            "cliui": "4.0.0",
+            "cliui": "4.1.0",
             "decamelize": "1.2.0",
             "find-up": "2.1.0",
             "get-caller-file": "1.0.2",

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/public/images/icons/eyeClosed.svg
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/images/icons/eyeClosed.svg 
b/modules/web-console/frontend/public/images/icons/eyeClosed.svg
new file mode 100644
index 0000000..32bcba8
--- /dev/null
+++ b/modules/web-console/frontend/public/images/icons/eyeClosed.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="18" height="8" viewBox="0 0 18 
8">
+    <g fill="currentColor" fill-rule="nonzero">
+        <path d="M.562 1.241l.876-.482A8.577 8.577 0 0 0 8.96 5.193 8.55 8.55 
0 0 0 16.481.76l.878.48A9.55 9.55 0 0 1 8.96 6.193 9.577 9.577 0 0 1 .562 
1.241z"/>
+        <path d="M1.59 
4.936c-.155.21-.427.32-.65.157-.222-.163-.198-.456-.043-.667l1.137-1.545c.155-.21.427-.32.65-.157.222.164.198.457.043.667L1.59
 4.936zM3.792 
6.545c-.136.223-.398.356-.633.212-.236-.144-.237-.439-.1-.661l1-1.637c.136-.223.399-.356.634-.212.236.144.237.439.1.66l-1
 1.638zM5.862 
7.834c-.254-.106-.3-.397-.2-.637l.741-1.77c.101-.242.34-.413.594-.306.255.107.3.397.2.637l-.74
 1.77c-.102.242-.34.413-.595.306zM16.484 
5.229l-1.137-1.546c-.155-.21-.179-.503.044-.667.223-.162.494-.053.65.158l1.136 
1.545c.155.21.18.503-.043.667-.223.163-.495.053-.65-.157zM14.282 
6.838l-1-1.637c-.138-.223-.137-.517.099-.661.236-.144.497-.011.634.212l1 
1.636c.137.223.136.518-.1.661-.235.144-.497.012-.633-.211zM11.575 
7.574l-.74-1.77c-.101-.24-.056-.53.2-.638.254-.106.492.064.594.306l.74 
1.77c.1.24.055.53-.2.637-.254.107-.493-.063-.594-.305z"/>
+    </g>
+</svg>

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/public/images/icons/eyeOpened.svg
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/images/icons/eyeOpened.svg 
b/modules/web-console/frontend/public/images/icons/eyeOpened.svg
new file mode 100644
index 0000000..74c3f78
--- /dev/null
+++ b/modules/web-console/frontend/public/images/icons/eyeOpened.svg
@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="18" height="12" viewBox="0 0 18 
12">
+    <g fill="currentColor" fill-rule="evenodd" transform="translate(1 1)">
+        <path fill-rule="nonzero" d="M16.428 5.418a9.567 9.567 0 0 1-8.402 
4.95A9.566 9.566 0 0 1-.375 5.418a1.008 1.008 0 0 1 0-.97C1.295 1.405 
4.505-.533 8.03-.5c2.576.025 4.734 1.039 6.439 2.694 1.219 1.183 2.214 2.756 
1.96 3.224zm-1.29-.838a9.278 9.278 0 0 0-1.366-1.669C12.241 1.425 10.32.523 
8.021.501 4.869.47 1.997 2.204.5 4.93a8.557 8.557 0 0 0 7.525 4.437c3.1 0 
5.905-1.642 7.419-4.241a5.366 5.366 0 0 0-.307-.546z"/>
+        <path fill-rule="nonzero" d="M8 9.517a4.5 4.5 0 1 1 0-9 4.5 4.5 0 0 1 
0 9zm0-1a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z"/>
+        <circle cx="8" cy="5" r="2"/>
+    </g>
+</svg>

http://git-wip-us.apache.org/repos/asf/ignite/blob/e0d1752a/modules/web-console/frontend/public/images/icons/index.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/images/icons/index.js 
b/modules/web-console/frontend/public/images/icons/index.js
index da7c3ab..62b3ab8 100644
--- a/modules/web-console/frontend/public/images/icons/index.js
+++ b/modules/web-console/frontend/public/images/icons/index.js
@@ -37,4 +37,5 @@ export collapse from './collapse.svg';
 export expand from './expand.svg';
 export home from './home.svg';
 export refresh from './refresh.svg';
-
+export {default as eyeOpened} from './eyeOpened.svg';
+export {default as eyeClosed} from './eyeClosed.svg';

Reply via email to