URL: https://github.com/freeipa/freeipa/pull/327
Author: pvomacka
 Title: #327: WebUI: RPC refactoring
Action: opened

PR body:
"""
Moved from ML ( 
https://www.redhat.com/archives/freeipa-devel/2016-November/msg00338.html ) to 
PR. 


"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/327/head:pr327
git checkout pr327
From 6f83cd83c29ff7e419f6c0f294fb84abc404d8c2 Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Thu, 28 Jul 2016 15:29:23 +0200
Subject: [PATCH 1/2] Refactoring of rpc module

The rpc module is now separated from display layer.

There are two new global topics:
- 'rpc-start' for showing the widget which indicates execution of rpc calls
- 'rpc-end' for hiding the widget which indicates execution of rpc calls.
These two global topics replace the original methods IPA.display_activity_icon() and
IPA.hide_activity_icon().

There is also new property of a command (notify_globally), which allows to turn off the widget
which indicates network activity. Instead of classic activity indicator there can be
called custom function at the beginning and at the end of network activity.

There are also changes in internal communication in rpc.js module. There are four new
events, two for calling on_success and on_error methods and two for calling custom functions
at the beginning and at the end of network activity.

https://fedorahosted.org/freeipa/ticket/6144
---
 install/ui/src/freeipa/certificate.js           | 60 +++++++++++++----
 install/ui/src/freeipa/ipa.js                   | 55 ++++++----------
 install/ui/src/freeipa/plugins/login.js         |  2 +-
 install/ui/src/freeipa/rpc.js                   | 85 +++++++++++++++++++------
 install/ui/src/freeipa/widget.js                | 16 +++--
 install/ui/src/freeipa/widgets/SyncOTPScreen.js |  7 +-
 6 files changed, 152 insertions(+), 73 deletions(-)

diff --git a/install/ui/src/freeipa/certificate.js b/install/ui/src/freeipa/certificate.js
index 9ab4002..4666b1a 100755
--- a/install/ui/src/freeipa/certificate.js
+++ b/install/ui/src/freeipa/certificate.js
@@ -780,19 +780,35 @@ IPA.cert.request_action = function(spec) {
 
 IPA.cert.perform_revoke = function(spec, sn, revocation_reason, cacn) {
 
-    spec.hide_activity_icon = spec.hide_activity_icon || false;
+    /**
+     * Sets whether activity notification box will be shown
+     * during executing command or not.
+     */
+    spec.notify_globally = spec.notify_globally === undefined ? true :
+            spec.notify_globally;
+
+
+    /**
+     * Specifies function which will be called before command execution starts.
+     */
+    spec.start_handler = spec.start_handler || null;
+
+    /**
+     * Specifies function which will be called after command execution ends.
+     */
+    spec.end_handler = spec.end_handler || null;
 
     rpc.command({
         entity: 'cert',
         method: 'revoke',
-        hide_activity_icon: spec.hide_activity_icon,
         args: [ sn ],
         options: {
             revocation_reason: revocation_reason,
             cacn: cacn
         },
-        notify_activity_start: spec.notify_activity_start,
-        notify_activity_end: spec.notify_activity_end,
+        notify_globally: spec.notify_globally,
+        start_handler: spec.start_handler,
+        end_handler: spec.end_handler,
         on_success: spec.on_success,
         on_error: spec.on_error
     }).execute();
@@ -906,6 +922,25 @@ IPA.cert.remove_hold_action = function(spec) {
 
 IPA.cert.perform_remove_hold = function(spec, sn, cacn) {
 
+    /**
+     * Sets whether activity notification box will be shown
+     * during executing command or not.
+     */
+    spec.notify_globally = spec.notify_globally === undefined ? true :
+            spec.notify_globally;
+
+
+    /**
+     * Specifies function which will be called before command execution starts.
+     */
+    spec.start_handler = spec.start_handler || null;
+
+    /**
+     * Specifies function which will be called after command execution ends.
+     */
+    spec.end_handler = spec.end_handler || null;
+
+
     rpc.command({
         entity: 'cert',
         method: 'remove_hold',
@@ -913,7 +948,10 @@ IPA.cert.perform_remove_hold = function(spec, sn, cacn) {
         options: {
             cacn: cacn
         },
-        on_success: spec.on_success
+        on_success: spec.on_success,
+        notify_globally: spec.notify_globally,
+        start_handler: spec.start_handler,
+        end_handler: spec.end_handler
     }).execute();
 };
 
@@ -1409,11 +1447,11 @@ IPA.cert.cert_widget = function(spec) {
             on_ok: function() {
 
                 var command_spec = {
-                    hide_activity_icon: true,
-                    notify_activity_end: function() {
+                    notify_globally: false,
+                    end_handler: function() {
                         that.spinner.emit('hide-spinner');
                     },
-                    notify_activity_start: function() {
+                    start_handler: function() {
                         that.spinner.emit('display-spinner');
                     },
                     on_success: function() {
@@ -1443,11 +1481,11 @@ IPA.cert.cert_widget = function(spec) {
             ok_label: '@i18n:buttons.remove_hold',
             on_ok: function () {
                 var command_spec = {
-                    hide_activity_icon: true,
-                    notify_activity_end: function() {
+                    notify_globally: false,
+                    end_handler: function() {
                         that.spinner.emit('hide-spinner');
                     },
-                    notify_activity_start: function() {
+                    start_handler: function() {
                         that.spinner.emit('display-spinner');
                     },
                     on_success: function() {
diff --git a/install/ui/src/freeipa/ipa.js b/install/ui/src/freeipa/ipa.js
index e8ad832..178bd03 100644
--- a/install/ui/src/freeipa/ipa.js
+++ b/install/ui/src/freeipa/ipa.js
@@ -340,29 +340,6 @@ var IPA = function () {
         return reg.entity.get(name);
     };
 
-    /**
-     * Display network activity indicator
-     */
-    that.display_activity_icon = function() {
-        that.network_call_count++;
-        if (that.network_call_count === 1) {
-            topic.publish('network-activity-start');
-        }
-    };
-
-    /**
-     * Hide network activity indicator
-     *
-     * - based on network_call_count
-     */
-    that.hide_activity_icon = function() {
-        that.network_call_count--;
-
-        if (0 === that.network_call_count) {
-            topic.publish('network-activity-end');
-        }
-    };
-
     that.obj_cls = declare([Evented]);
 
     return that;
@@ -391,13 +368,13 @@ IPA.get_credentials = function() {
 
     function error_handler(xhr, text_status, error_thrown) {
         d.resolve(xhr.status);
-        IPA.hide_activity_icon();
+        topic.publish('rpc-end');
     }
 
     function success_handler(data, text_status, xhr) {
         auth.current.set_authenticated(true, 'kerberos');
         d.resolve(xhr.status);
-        IPA.hide_activity_icon();
+        topic.publish('rpc-end');
     }
 
     var request = {
@@ -407,7 +384,9 @@ IPA.get_credentials = function() {
         success: success_handler,
         error: error_handler
     };
-    IPA.display_activity_icon();
+
+    topic.publish('rpc-start');
+
     $.ajax(request);
 
     return d.promise;
@@ -439,7 +418,8 @@ IPA.logout = function() {
     }
 
     function success_handler(data, text_status, xhr) {
-        IPA.hide_activity_icon();
+        topic.publish('rpc-end');
+
         if (data && data.error) {
             show_error(data.error.message);
         } else {
@@ -448,7 +428,8 @@ IPA.logout = function() {
     }
 
     function error_handler(xhr, text_status, error_thrown) {
-        IPA.hide_activity_icon();
+        topic.publish('rpc-end');
+
         if (xhr.status === 401) {
             reload();
         } else {
@@ -467,7 +448,8 @@ IPA.logout = function() {
         success: success_handler,
         error: error_handler
     };
-    IPA.display_activity_icon();
+    topic.publish('rpc-start');
+
     $.ajax(request);
 };
 
@@ -485,7 +467,8 @@ IPA.login_password = function(username, password) {
     var d = new Deferred();
 
     function success_handler(data, text_status, xhr) {
-        IPA.hide_activity_icon();
+        topic.publish('rpc-end');
+
         result = 'success';
         auth.current.set_authenticated(true, 'password');
         d.resolve(result);
@@ -493,7 +476,8 @@ IPA.login_password = function(username, password) {
 
     function error_handler(xhr, text_status, error_thrown) {
 
-        IPA.hide_activity_icon();
+        topic.publish('rpc-end');
+
         if (xhr.status === 401) {
             var reason = xhr.getResponseHeader("X-IPA-Rejection-Reason");
 
@@ -526,7 +510,8 @@ IPA.login_password = function(username, password) {
         error: error_handler
     };
 
-    IPA.display_activity_icon();
+    topic.publish('rpc-start');
+
     $.ajax(request);
 
     return d.promise;
@@ -558,6 +543,8 @@ IPA.reset_password = function(username, old_password, new_password, otp) {
 
     function success_handler(data, text_status, xhr) {
 
+        topic.publish('rpc-end');
+
         result.status = xhr.getResponseHeader("X-IPA-Pwchange-Result") || status;
 
         if (result.status === 'policy-error') {
@@ -571,6 +558,7 @@ IPA.reset_password = function(username, old_password, new_password, otp) {
     }
 
     function error_handler(xhr, text_status, error_thrown) {
+        topic.publish('rpc-end');
         return result;
     }
 
@@ -596,9 +584,8 @@ IPA.reset_password = function(username, old_password, new_password, otp) {
         error: error_handler
     };
 
-    IPA.display_activity_icon();
+    topic.publish('rpc-start');
     $.ajax(request);
-    IPA.hide_activity_icon();
 
     return result;
 };
diff --git a/install/ui/src/freeipa/plugins/login.js b/install/ui/src/freeipa/plugins/login.js
index c555ed2..2a2cf69 100644
--- a/install/ui/src/freeipa/plugins/login.js
+++ b/install/ui/src/freeipa/plugins/login.js
@@ -97,4 +97,4 @@ define(['dojo/_base/declare',
     });
 
     return login;
-});
\ No newline at end of file
+});
diff --git a/install/ui/src/freeipa/rpc.js b/install/ui/src/freeipa/rpc.js
index f3cc48c..7ae1b64 100644
--- a/install/ui/src/freeipa/rpc.js
+++ b/install/ui/src/freeipa/rpc.js
@@ -25,13 +25,15 @@
 define([
     'dojo/_base/lang',
     'dojo/Deferred',
+    'dojo/on',
+    'dojo/topic',
     './auth',
     './ipa',
     './text',
     './util',
     'exports'
    ],
-   function(lang, Deferred, auth, IPA, text, util, rpc /*exports*/) {
+   function(lang, Deferred, on, topic, auth, IPA, text, util, rpc /*exports*/) {
 
 /**
  * Call an IPA command over JSON-RPC.
@@ -99,9 +101,10 @@ rpc.command = function(spec) {
     /**
      * Allow turning off the activity icon.
      *
-     * @property {Boolean} show=true
+     * @property {Boolean} notify_globally=true
      */
-    that.hide_activity_icon = spec.hide_activity_icon || false;
+    that.notify_globally = spec.notify_globally === undefined ? true :
+        spec.notify_globally;
 
     /**
      * Allow set function which will be called when the activity of the command
@@ -109,7 +112,7 @@ rpc.command = function(spec) {
      *
      * @property {Function}
      */
-    that.notify_activity_start = spec.notify_activity_start || null;
+    that.start_handler = spec.start_handler || null;
 
     /**
      * Allow set function which will be called when the activity of the command
@@ -117,7 +120,7 @@ rpc.command = function(spec) {
      *
      * @property {Function}
      */
-    that.notify_activity_end = spec.notify_activity_end || null;
+    that.end_handler = spec.end_handler || null;
 
     /** @property {string} error_message Default error message */
     that.error_message = text.get(spec.error_message || '@i18n:dialogs.batch_error_message', 'Some operations failed.');
@@ -223,11 +226,11 @@ rpc.command = function(spec) {
     };
 
     that.handle_notify_execution_end = function() {
-        if (that.hide_activity_icon) {
-            if (that.notify_activity_end) that.notify_activity_end();
+        if (that.notify_globally) {
+            topic.publish('rpc-end');
         }
         else {
-            IPA.hide_activity_icon();
+            that.emit('end');
         }
     };
 
@@ -285,7 +288,7 @@ rpc.command = function(spec) {
 
             var self = this;
             function proceed() {
-                // error_handler() calls IPA.hide_activity_icon()
+                // error_handler() publishes 'rpc-end'
                 error_handler.call(self, xhr, text_status, error_thrown);
             }
 
@@ -375,7 +378,7 @@ rpc.command = function(spec) {
         function success_handler(data, text_status, xhr) {
 
             if (!data) {
-                // error_handler() calls IPA.hide_activity_icon()
+                // error_handler() publishes 'rpc-end'
                 error_handler.call(this, xhr, text_status, /* error_thrown */ {
                     name: text.get('@i18n:errors.http_error', 'HTTP Error')+' '+xhr.status,
                     url: this.url,
@@ -390,7 +393,7 @@ rpc.command = function(spec) {
                 window.location.reload();
 
             } else if (data.error) {
-                // error_handler() calls IPA.hide_activity_icon()
+                // error_handler() publishes 'rpc-end'
                 error_handler.call(this, xhr, text_status,  /* error_thrown */ {
                     name: text.get('@i18n:errors.ipa_error', 'IPA Error') + ' ' +
                           data.error.code + ': ' + data.error.name,
@@ -419,14 +422,24 @@ rpc.command = function(spec) {
 
                     dialog.on_ok = function() {
                         dialog.close();
-                        if (that.on_success) that.on_success.call(ajax, data, text_status, xhr);
+                        that.emit('success', {
+                            that: ajax,
+                            data: data,
+                            text_status: text_status,
+                            xhr: xhr
+                        });
                     };
 
                     dialog.open();
 
                 } else {
                     //custom success handling, maintaining AJAX call's context
-                    if (that.on_success) that.on_success.call(this, data, text_status, xhr);
+                    that.emit('success', {
+                        that: this,
+                        data: data,
+                        text_status: text_status,
+                        xhr: xhr
+                    });
                 }
                 that.process_warnings(data.result);
                 deferred.resolve({
@@ -453,11 +466,11 @@ rpc.command = function(spec) {
             error: error_handler_login
         };
 
-        if (that.hide_activity_icon) {
-            if (that.notify_activity_start) that.notify_activity_start();
+        if (that.notify_globally) {
+            topic.publish('rpc-start');
         }
         else {
-            IPA.display_activity_icon();
+            that.emit('start');
         }
 
         $.ajax(that.request);
@@ -539,6 +552,26 @@ rpc.command = function(spec) {
         return string;
     };
 
+    that.register_handlers = function() {
+        on(that, 'start', function() {
+            if (that.start_handler) that.start_handler();
+        });
+
+        on(that, 'end', function() {
+            if (that.end_handler) that.end_handler();
+        });
+
+        on(that, 'success', function(e) {
+            if (that.on_success) that.on_success(e.data, e.text_status, e.xhr);
+        });
+
+        on(that, 'error', function(xhr, text_status, error_thrown) {
+            if (that.on_error) that.on_error(xhr, text_status, error_thrown);
+        });
+    };
+
+    that.register_handlers();
+
     return that;
 };
 
@@ -674,11 +707,14 @@ rpc.batch_command = function(spec) {
                 var failed = that.get_failed(command, result, text_status, xhr);
                 that.errors.add_range(failed);
 
-                if (command.on_success) command.on_success.call(this, result, text_status, xhr);
+                command.emit('success', {
+                    data: result,
+                    text_status: text_status,
+                    xhr: xhr
+                });
             }
         }
 
-        //check for partial errors and show error dialog
         if (that.show_error && that.errors.errors.length > 0) {
             var ajax = this;
             var dialog = IPA.error_dialog({
@@ -695,13 +731,22 @@ rpc.batch_command = function(spec) {
 
             dialog.on_ok = function() {
                 dialog.close();
-                if (that.on_success) that.on_success.call(ajax, data, text_status, xhr);
+                that.emit('success', {
+                    that: ajax,
+                    data: data,
+                    text_status: text_status,
+                    xhr: xhr
+                });
             };
 
             dialog.open();
 
         } else {
-            if (that.on_success) that.on_success.call(this, data, text_status, xhr);
+            that.emit('success', {
+                data: data,
+                text_status: text_status,
+                xhr: xhr
+            });
         }
     };
 
diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
index 041eaa2..1d98cc4 100644
--- a/install/ui/src/freeipa/widget.js
+++ b/install/ui/src/freeipa/widget.js
@@ -6977,6 +6977,8 @@ exp.activity_widget = IPA.activity_widget = function(spec) {
 
     that.icon = spec.icon || 'fa fa-spinner fa-spin';
 
+    that.connection_counter = 0;
+
     /**
      * Operation mode
      *
@@ -6986,8 +6988,8 @@ exp.activity_widget = IPA.activity_widget = function(spec) {
      */
     that.mode = spec.mode || "dots";
 
-    that.activate_event = spec.activate_event || 'network-activity-start';
-    that.deactivate_event = spec.deactivate_event || 'network-activity-end';
+    that.activate_event = spec.activate_event || 'rpc-start';
+    that.deactivate_event = spec.deactivate_event || 'rpc-end';
 
     that.create = function(container) {
         that.widget_create(container);
@@ -7012,10 +7014,15 @@ exp.activity_widget = IPA.activity_widget = function(spec) {
         }
         that.set_visible(that.visible);
         topic.subscribe(that.activate_event, function() {
-            that.show();
+            ++that.connection_counter;
+
+            if (that.connection_counter === 1) that.show();
         });
         topic.subscribe(that.deactivate_event, function() {
-            that.hide();
+            --that.connection_counter;
+
+            if (that.connection_counter === 0) that.hide();
+            if (that.connection_counter < 0) that.connection_counter = 0;
         });
     };
 
@@ -7036,6 +7043,7 @@ exp.activity_widget = IPA.activity_widget = function(spec) {
         that.toggle_class('closed', true);
         that.row_node.detach(); // to save CPU time (spinner icon)
         that.toggle_timer(false);
+
     };
 
     that.show = function() {
diff --git a/install/ui/src/freeipa/widgets/SyncOTPScreen.js b/install/ui/src/freeipa/widgets/SyncOTPScreen.js
index 09d1254..afb9137 100644
--- a/install/ui/src/freeipa/widgets/SyncOTPScreen.js
+++ b/install/ui/src/freeipa/widgets/SyncOTPScreen.js
@@ -23,6 +23,7 @@ define(['dojo/_base/declare',
         'dojo/dom-construct',
         'dojo/dom-style',
         'dojo/query',
+        'dojo/topic',
         'dojo/on',
         '../ipa',
         '../auth',
@@ -32,7 +33,7 @@ define(['dojo/_base/declare',
         '../util',
         './LoginScreenBase'
        ],
-       function(declare, Deferred, construct, dom_style, query, on,
+       function(declare, Deferred, construct, dom_style, query, topic, on,
                 IPA, auth, reg, FieldBinder, text, util, LoginScreenBase) {
 
 
@@ -150,7 +151,7 @@ define(['dojo/_base/declare',
             var handler = function(data, text_status, xhr) {
                 var result = xhr.getResponseHeader("X-IPA-TokenSync-Result");
                 result = result || 'error';
-                IPA.hide_activity_icon();
+                topic.publish('rpc-end');
                 d.resolve(result);
             };
 
@@ -165,7 +166,7 @@ define(['dojo/_base/declare',
                 error: handler
             };
 
-            IPA.display_activity_icon();
+            topic.publish('rpc-start');
             $.ajax(request);
             return d.promise;
         },

From cbfcc7c8d0ffe918105c16205a0afa8b044a8494 Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Tue, 9 Aug 2016 12:43:09 +0200
Subject: [PATCH 2/2] Change activity text while loading metadata

After log in into webui there was 'Authenticating' sign even during loading metadata.
Now while data are loading there is 'Loading data' text. This change requires new global
topic 'set-activity' of activity widget. So for now there is possibility to change
every activity string during running phase just by publishing 'set-activity' topic
and setting new text as first parameter.

Part of: https://fedorahosted.org/freeipa/ticket/6144
---
 install/ui/src/freeipa/ipa.js      | 3 +++
 install/ui/src/freeipa/widget.js   | 5 +++++
 install/ui/test/data/ipa_init.json | 1 +
 ipaserver/plugins/internal.py      | 1 +
 4 files changed, 10 insertions(+)

diff --git a/install/ui/src/freeipa/ipa.js b/install/ui/src/freeipa/ipa.js
index 178bd03..46b033a 100644
--- a/install/ui/src/freeipa/ipa.js
+++ b/install/ui/src/freeipa/ipa.js
@@ -276,6 +276,9 @@ var IPA = function () {
      * @param {Function} params.on_error
      */
     that.init_metadata = function(params) {
+        var loading = text.get('@i18n:login.loading_md');
+
+        topic.publish('set-activity', loading);
 
         var objects = rpc.command({
             name: 'ipa_init_objects',
diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
index 1d98cc4..6ad8aad 100644
--- a/install/ui/src/freeipa/widget.js
+++ b/install/ui/src/freeipa/widget.js
@@ -6990,6 +6990,7 @@ exp.activity_widget = IPA.activity_widget = function(spec) {
 
     that.activate_event = spec.activate_event || 'rpc-start';
     that.deactivate_event = spec.deactivate_event || 'rpc-end';
+    that.set_activity_event = 'set-activity';
 
     that.create = function(container) {
         that.widget_create(container);
@@ -7024,6 +7025,10 @@ exp.activity_widget = IPA.activity_widget = function(spec) {
             if (that.connection_counter === 0) that.hide();
             if (that.connection_counter < 0) that.connection_counter = 0;
         });
+
+        topic.subscribe(that.set_activity_event, function(new_text) {
+             that.text = new_text;
+        });
     };
 
     that.toggle_timer = function(start) {
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 514206a..6d11e73 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -186,6 +186,7 @@
                         "form_auth": "<i class=\"fa fa-info-circle\"></i> To login with <strong>username and password</strong>, enter them in the corresponding fields, then click Login.",
                         "header": "Logged In As",
                         "krb_auth_msg": "<i class=\"fa fa-info-circle\"></i> To login with <strong>Kerberos</strong>, please make sure you have valid tickets (obtainable via kinit) and <a href='http://${host}/ipa/config/unauthorized.html'>configured</a> the browser correctly, then click Login.",
+                        "loading_md": "Loading data",
                         "login": "Login",
                         "logout": "Logout",
                         "logout_error": "Logout error",
diff --git a/ipaserver/plugins/internal.py b/ipaserver/plugins/internal.py
index 6107a14..0a8139e 100644
--- a/ipaserver/plugins/internal.py
+++ b/ipaserver/plugins/internal.py
@@ -335,6 +335,7 @@ class i18n_messages(Command):
             "form_auth": _("<i class=\"fa fa-info-circle\"></i> To login with <strong>username and password</strong>, enter them in the corresponding fields, then click Login."),
             "header": _("Logged In As"),
             "krb_auth_msg": _("<i class=\"fa fa-info-circle\"></i> To login with <strong>Kerberos</strong>, please make sure you have valid tickets (obtainable via kinit) and <a href='http://${host}/ipa/config/unauthorized.html'>configured</a> the browser correctly, then click Login."),
+            "loading_md": _("Loading data"),
             "login": _("Login"),
             "logout": _("Logout"),
             "logout_error": _("Logout error"),
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to