IGNITE-8519 Web Console: Refactored security token UI/UX.

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

Branch: refs/heads/ignite-8446
Commit: 81b6b2d49284da67ff279e5f8e0062934d73eaab
Parents: 219bc81
Author: Ilya Borisov <[email protected]>
Authored: Fri Jun 29 11:13:16 2018 +0700
Committer: Alexey Kuznetsov <[email protected]>
Committed: Fri Jun 29 11:13:16 2018 +0700

----------------------------------------------------------------------
 .../fixtures/user-profile/credentials.js        |  9 +-
 .../e2e/testcafe/page-models/pageProfile.js     |  4 +-
 .../copyInputValueButton.directive.js           | 86 ++++++++++++++++++++
 .../frontend/app/components/form-field/index.js |  5 +-
 .../app/components/form-field/style.scss        | 29 +++++++
 .../app/components/page-profile/controller.js   |  2 +-
 .../app/components/page-profile/template.pug    | 22 +++--
 .../app/modules/agent/AgentModal.service.js     |  9 +-
 .../frontend/public/images/icons/copy.svg       |  3 +
 .../frontend/public/images/icons/index.js       | 41 +++++-----
 .../views/templates/agent-download.tpl.pug      | 17 +++-
 11 files changed, 187 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/e2e/testcafe/fixtures/user-profile/credentials.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/e2e/testcafe/fixtures/user-profile/credentials.js 
b/modules/web-console/e2e/testcafe/fixtures/user-profile/credentials.js
index b76a736..ea18aaf 100644
--- a/modules/web-console/e2e/testcafe/fixtures/user-profile/credentials.js
+++ b/modules/web-console/e2e/testcafe/fixtures/user-profile/credentials.js
@@ -39,13 +39,16 @@ fixture('Checking user credentials change')
 test('Testing secure token change', async(t) => {
     await t.click(pageProfile.securityToken.panel.heading);
 
-    const currentToken = await pageProfile.securityToken.value.innerText;
+    const currentToken = await pageProfile.securityToken.value.control.value;
 
     await t
         .click(pageProfile.securityToken.generateTokenButton)
-        .expect(confirmation.body.innerText).contains('Are you sure you want 
to change security token?')
+        .expect(confirmation.body.innerText).contains(
+`Are you sure you want to change security token?
+If you change the token you will need to restart the agent.`
+        )
         .click(confirmation.confirmButton)
-        
.expect(pageProfile.securityToken.value.innerText).notEql(currentToken);
+        
.expect(pageProfile.securityToken.value.control.value).notEql(currentToken);
 });
 
 test('Testing password change', async(t) => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/e2e/testcafe/page-models/pageProfile.js
----------------------------------------------------------------------
diff --git a/modules/web-console/e2e/testcafe/page-models/pageProfile.js 
b/modules/web-console/e2e/testcafe/page-models/pageProfile.js
index a2eb1db..8a81f36 100644
--- a/modules/web-console/e2e/testcafe/page-models/pageProfile.js
+++ b/modules/web-console/e2e/testcafe/page-models/pageProfile.js
@@ -28,8 +28,8 @@ export const pageProfile = {
     company: new CustomFormField({id: 'companyInput'}),
     securityToken: {
         panel: new PanelCollapsible('security token'),
-        generateTokenButton: Selector('i').withAttribute('ng-click', 
'$ctrl.generateToken()'),
-        value: Selector('#current-security-token')
+        generateTokenButton: Selector('a').withText('Generate Random Security 
Token?'),
+        value: new CustomFormField({id: 'securityTokenInput'})
     },
     password: {
         panel: new PanelCollapsible('password'),

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/frontend/app/components/form-field/copyInputValueButton.directive.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/components/form-field/copyInputValueButton.directive.js
 
b/modules/web-console/frontend/app/components/form-field/copyInputValueButton.directive.js
new file mode 100644
index 0000000..06500e4
--- /dev/null
+++ 
b/modules/web-console/frontend/app/components/form-field/copyInputValueButton.directive.js
@@ -0,0 +1,86 @@
+/*
+ * 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 template = `
+    <svg
+        class='copy-input-value-button'
+        ignite-icon='copy'
+        ignite-copy-to-clipboard='{{ $ctrl.value }}'
+        bs-tooltip=''
+        data-title='{{::$ctrl.title}}'
+        ng-show='$ctrl.value'
+    ></svg>
+`;
+
+class CopyInputValueButtonController {
+    /** @type {ng.INgModelController} */
+    ngModel;
+
+    /**
+     * Tooltip title
+     * @type {string}
+     */
+    title;
+
+    static $inject = ['$element', '$compile', '$scope'];
+
+    /**
+     * @param {JQLite} $element
+     * @param {ng.ICompileService} $compile
+     * @param {ng.IScope} $scope
+     */
+    constructor($element, $compile, $scope) {
+        this.$element = $element;
+        this.$compile = $compile;
+        this.$scope = $scope;
+    }
+
+    $postLink() {
+        this.buttonScope = this.$scope.$new(true);
+        this.buttonScope.$ctrl = this;
+        this.$compile(template)(this.buttonScope, (clone) => {
+            this.$element[0].parentElement.appendChild(clone[0]);
+            this.buttonElement = clone;
+        });
+    }
+
+    $onDestroy() {
+        this.buttonScope.$ctrl = null;
+        this.buttonScope.$destroy();
+        this.buttonElement.remove();
+        this.buttonElement = this.$element = this.ngModel = null;
+    }
+
+    get value() {
+        return this.ngModel
+            ? this.ngModel.$modelValue
+            : void 0;
+    }
+}
+
+export function directive() {
+    return {
+        scope: false,
+        bindToController: {
+            title: '@copyInputValueButton'
+        },
+        controller: CopyInputValueButtonController,
+        require: {
+            ngModel: 'ngModel'
+        }
+    };
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/frontend/app/components/form-field/index.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/form-field/index.js 
b/modules/web-console/frontend/app/components/form-field/index.js
index 323c30a..077ace0 100644
--- a/modules/web-console/frontend/app/components/form-field/index.js
+++ b/modules/web-console/frontend/app/components/form-field/index.js
@@ -16,8 +16,11 @@
  */
 
 import angular from 'angular';
+import './style.scss';
 import {directive as showValidationError} from 
'./showValidationError.directive';
+import {directive as copyInputValue} from './copyInputValueButton.directive';
 
 export default angular
     .module('ignite-console.form-field', [])
-    .directive('ngModel', showValidationError);
+    .directive('ngModel', showValidationError)
+    .directive('copyInputValueButton', copyInputValue);

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/frontend/app/components/form-field/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/form-field/style.scss 
b/modules/web-console/frontend/app/components/form-field/style.scss
new file mode 100644
index 0000000..2cf767f
--- /dev/null
+++ b/modules/web-console/frontend/app/components/form-field/style.scss
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+.copy-input-value-button {
+    position: absolute;
+    top: 31px;
+    right: 10px;
+
+    &:hover {
+        @import 'public/stylesheets/variables';
+
+        color: $ignite-brand-success;
+        cursor: pointer;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/frontend/app/components/page-profile/controller.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/components/page-profile/controller.js 
b/modules/web-console/frontend/app/components/page-profile/controller.js
index c67a603..2c786f0 100644
--- a/modules/web-console/frontend/app/components/page-profile/controller.js
+++ b/modules/web-console/frontend/app/components/page-profile/controller.js
@@ -40,7 +40,7 @@ export default class PageProfileController {
     }
 
     generateToken() {
-        this.Confirm.confirm('Are you sure you want to change security token?')
+        this.Confirm.confirm('Are you sure you want to change security 
token?<br>If you change the token you will need to restart the agent.')
             .then(() => this.ui.user.token = 
this.LegacyUtils.randomString(20));
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/frontend/app/components/page-profile/template.pug
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/components/page-profile/template.pug 
b/modules/web-console/frontend/app/components/page-profile/template.pug
index eafde6b..fb95793 100644
--- a/modules/web-console/frontend/app/components/page-profile/template.pug
+++ b/modules/web-console/frontend/app/components/page-profile/template.pug
@@ -99,14 +99,20 @@ div
                         | {{ $panel.opened ? 'Cancel security token 
changing...' : 'Show security token...' }}
                     panel-content
                         .row
-                            .col-25
-                                label.required Security token:
-                            .col-75
-                                label#current-security-token 
{{$ctrl.ui.user.token || 'No security token. Regenerate please.'}}
-                                label
-                                    
i.tipLabel.fa.fa-refresh(ng-click='$ctrl.generateToken()' bs-tooltip='' 
data-title='Generate random security token')
-                                    
i.tipLabel.fa.fa-clipboard(ignite-copy-to-clipboard='{{$ctrl.ui.user.token}}' 
bs-tooltip='' data-title='Copy security token to clipboard')
-                                    i.tipLabel.icon-help(ng-if=lines 
bs-tooltip='' data-title='The security token is used for authorization of web 
agent')
+                            .col-50
+                                +form-field__text({
+                                    label: 'Security Token:',
+                                    model: '$ctrl.ui.user.token',
+                                    tip: 'The security token is used for 
authentication of Web agent',
+                                    name: '"securityToken"',
+                                    placeholder: 'No security token. 
Regenerate please.'
+                                })(
+                                    autocomplete='security-token'
+                                    ng-disabled='::true'
+                                    copy-input-value-button='Copy security 
token to clipboard'
+                                )
+                            .col-50
+                                a(ng-click='$ctrl.generateToken()') Generate 
Random Security Token?
 
         .row
             .col-50

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/frontend/app/modules/agent/AgentModal.service.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/modules/agent/AgentModal.service.js 
b/modules/web-console/frontend/app/modules/agent/AgentModal.service.js
index 52abf6d..67e5cda 100644
--- a/modules/web-console/frontend/app/modules/agent/AgentModal.service.js
+++ b/modules/web-console/frontend/app/modules/agent/AgentModal.service.js
@@ -23,6 +23,7 @@ export default class AgentModal {
     constructor($root, $state, $modal, Messages) {
         const self = this;
 
+        this.$root = $root;
         self.$state = $state;
         self.Messages = Messages;
 
@@ -36,11 +37,13 @@ export default class AgentModal {
             controllerAs: 'ctrl'
         });
 
-        $root.$on('user', (event, user) => self.user = user);
+        this.off = $root.$on('user', (event, user) => self.user = user);
     }
 
     hide() {
         this.modal.hide();
+        this.off();
+        this.off = null;
     }
 
     /**
@@ -86,4 +89,8 @@ export default class AgentModal {
 
         self.modal.$promise.then(self.modal.show);
     }
+
+    get securityToken() {
+        return this.$root.user.becameToken || this.$root.user.token;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/frontend/public/images/icons/copy.svg
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/images/icons/copy.svg 
b/modules/web-console/frontend/public/images/icons/copy.svg
new file mode 100644
index 0000000..b04d4ea
--- /dev/null
+++ b/modules/web-console/frontend/public/images/icons/copy.svg
@@ -0,0 +1,3 @@
+<svg version="1.1" viewBox="0 0 16 19" xmlns="http://www.w3.org/2000/svg";>
+ <path class="st0" d="m11.8 0h-10.1c-0.9 0-1.7 0.8-1.7 
1.7v11.8h1.7v-11.8h10.1v-1.7zm2.5 3.4h-9.3c-0.9 0-1.7 0.8-1.7 1.7v11.8c0 0.9 
0.8 1.7 1.7 1.7h9.3c0.9 0 1.7-0.8 1.7-1.7v-11.8c0-1-0.8-1.7-1.7-1.7zm-9.2 
1.7h9.3v11.8h-9.3z" fill="currentColor"/>
+</svg>

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/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 5a8d851..d101901 100644
--- a/modules/web-console/frontend/public/images/icons/index.js
+++ b/modules/web-console/frontend/public/images/icons/index.js
@@ -15,30 +15,31 @@
  * limitations under the License.
  */
 
-export csv from './csv.svg';
-export cross from './cross.svg';
-export gear from './gear.svg';
+export alert from './alert.svg';
+export attention from './attention.svg';
+export check from './check.svg';
+export checkmark from './checkmark.svg';
 export clock from './clock.svg';
-export manual from './manual.svg';
+export collapse from './collapse.svg';
+export connectedClusters from './connectedClusters.svg';
+export copy from './copy.svg';
+export cross from './cross.svg';
+export csv from './csv.svg';
 export download from './download.svg';
+export exclamation from './exclamation.svg';
+export exit from './exit.svg';
+export expand from './expand.svg';
+export eyeClosed from './eyeClosed.svg';
+export eyeOpened from './eyeOpened.svg';
 export filter from './filter.svg';
+export gear from './gear.svg';
+export home from './home.svg';
+export info from './info.svg';
+export lockClosed from './lockClosed.svg';
+export lockOpened from './lockOpened.svg';
+export manual from './manual.svg';
 export plus from './plus.svg';
+export refresh from './refresh.svg';
 export search from './search.svg';
-export checkmark from './checkmark.svg';
 export sort from './sort.svg';
-export info from './info.svg';
-export connectedClusters from './connectedClusters.svg';
-export check from './check.svg';
 export structure from './structure.svg';
-export alert from './alert.svg';
-export attention from './attention.svg';
-export exclamation from './exclamation.svg';
-export collapse from './collapse.svg';
-export expand from './expand.svg';
-export home from './home.svg';
-export refresh from './refresh.svg';
-export eyeOpened from './eyeOpened.svg';
-export eyeClosed from './eyeClosed.svg';
-export lockOpened from './lockOpened.svg';
-export lockClosed from './lockClosed.svg';
-export exit from './exit.svg';

http://git-wip-us.apache.org/repos/asf/ignite/blob/81b6b2d4/modules/web-console/frontend/views/templates/agent-download.tpl.pug
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/views/templates/agent-download.tpl.pug 
b/modules/web-console/frontend/views/templates/agent-download.tpl.pug
index fdb3a05..4da9fad 100644
--- a/modules/web-console/frontend/views/templates/agent-download.tpl.pug
+++ b/modules/web-console/frontend/views/templates/agent-download.tpl.pug
@@ -14,6 +14,8 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 
+include /app/helpers/jade/mixins
+
 .modal.modal--ignite.theme--ignite.center(tabindex='-1' role='dialog')
     .modal-dialog(ng-switch='ctrl.status')
         .modal-content(ng-switch-when='agentMissing')
@@ -30,10 +32,17 @@
                 .modal-advanced-options
                     i.fa(ng-class='showToken ? "fa-chevron-circle-down" : 
"fa-chevron-circle-right"' ng-click='showToken = !showToken')
                     a(ng-click='showToken = !showToken') {{showToken ? 'Hide 
security token...' : 'Show security token...'}}
-                p(ng-show='showToken')
-                    label.labelField Security token: {{user.becameToken || 
user.token}}
-                    
i.tipLabel.fa.fa-clipboard(ignite-copy-to-clipboard='{{user.becameToken || 
user.token}}' bs-tooltip='' data-title='Copy security token to clipboard')
-                    i.tipLabel.icon-help(ng-if=lines bs-tooltip='' 
data-title='The security token is used for authorization of web agent')
+                div(ng-show='showToken')
+                    +form-field__text({
+                        label: 'Security Token:',
+                        model: 'ctrl.securityToken',
+                        tip: 'The security token is used for authentication of 
web agent',
+                        name: '"securityToken"'
+                    })(
+                        autocomplete='security-token'
+                        ng-disabled='::true'
+                        copy-input-value-button='Copy security token to 
clipboard'
+                    )
 
             .modal-footer
                 
button.btn-ignite.btn-ignite--link-success(ng-click='ctrl.back()') 
{{::ctrl.backText}}

Reply via email to