Hi,

Please review the attached patch. It can be tested by moving one of
the JSON files in test/data somewhere else. Thanks!

The ipa_cmd() has been modified such that when an error occurs a
dialog box will appear showing the error message with 2 buttons:
Retry and Cancel. If Retry is clicked, it will attempt to execute
the same operation again. If Cancel is clicked, the operation will
be canceled and the control is returned to the caller.

The associate.js, details.js, entity.js, search.js, and webui.js
have been modified to display the error message inside the page.
This behavior can be changed in the future (e.g. redirect to error
page).

The navigation.js and webui.js have been modified to render only
the visible tabs. This improves the performance and reduce hidden
errors.

Some variables/functions also have been renamed for consistency.

--
Endi S. Dewata
>From 5e796d644c8a84fc133e191f2b1a701501950711 Mon Sep 17 00:00:00 2001
From: Endi S. Dewata <edew...@redhat.com>
Date: Tue, 28 Sep 2010 15:54:27 -0500
Subject: [PATCH] Added error handler for ipa_cmd().

The ipa_cmd() has been modified such that when an error occurs a
dialog box will appear showing the error message with 2 buttons:
Retry and Cancel. If Retry is clicked, it will attempt to execute
the same operation again. If Cancel is clicked, the operation will
be canceled and the control is returned to the caller.

The associate.js, details.js, entity.js, search.js, and webui.js
have been modified to display the error message inside the page.
This behavior can be changed in the future (e.g. redirect to error
page).

The navigation.js and webui.js have been modified to render only
the visible tabs. This improves the performance and reduce hidden
errors.

Some variables/functions also have been renamed for consistency.
---
 install/static/associate.js  |   42 ++++++++++++++--------------
 install/static/details.js    |   27 ++++++++++++------
 install/static/entity.js     |    5 ++-
 install/static/ipa.js        |   28 ++++++++++++++++---
 install/static/navigation.js |    4 +--
 install/static/search.js     |   38 +++++++++++++++++---------
 install/static/webui.js      |   60 ++++++++++++++++++++++++++---------------
 7 files changed, 130 insertions(+), 74 deletions(-)

diff --git a/install/static/associate.js b/install/static/associate.js
index 207c745..1b65a2d 100644
--- a/install/static/associate.js
+++ b/install/static/associate.js
@@ -222,30 +222,30 @@ function AssociationList(obj, pkey, manyObj, associationColumns, jobj)
     this.manyObj = manyObj;
     this.parentTab = jobj;
 
-    this.populate = function(userData) {
-       var tbody = this.parentTab.find('.search-table tbody');
-       tbody.empty();
-       var associationList = userData.result.result[this.associationColumns[0].column];
-       for (var j = 0; j < associationList.length; j++){
-            var row  = $("<tr/>").appendTo(tbody);
-            for (var k = 0; k < associationColumns.length ;k++){
-                var column = this.associationColumns[k].column;
-                $("<td></td>",{
-                    html: userData.result.result[column][j]
-                }).appendTo(row);
+    this.refresh = function() {
+
+        function refresh_on_success(userData) {
+           var tbody = this.parentTab.find('.search-table tbody');
+           tbody.empty();
+           var associationList = userData.result.result[this.associationColumns[0].column];
+           for (var j = 0; j < associationList.length; j++){
+                var row  = $("<tr/>").appendTo(tbody);
+                for (var k = 0; k < associationColumns.length ;k++){
+                    var column = this.associationColumns[k].column;
+                    $("<td></td>",{
+                        html: userData.result.result[column][j]
+                    }).appendTo(row);
+                }
             }
         }
-    }
 
-    this.refresh = function() {
-        ipa_cmd( 'show', [this.pkey], {},
-                 function(result){
-                     form.populate(result);
-                 },
-                 function(){
-                     alert("associationListFailure");
-                 },
-                 form.obj);
+        function refresh_on_error(xhr, text_status, error_thrown) {
+            var search_results = $('.search-results', jobj).empty();
+            search_results.append('<p>Error: '+error_thrown.name+'</p>');
+            search_results.append('<p>'+error_thrown.message+'</p>');
+        }
+
+        ipa_cmd('show', [this.pkey], {}, refresh_on_success, refresh_on_error, form.obj);
     }
 
     this.setup = function() {
diff --git a/install/static/details.js b/install/static/details.js
index f68c773..b6efc1e 100644
--- a/install/static/details.js
+++ b/install/static/details.js
@@ -37,20 +37,24 @@ function ipa_details_create(obj_name, dls, container)
     container.attr('title', obj_name);
     container.addClass('details-container');
 
-    container.append('<div class="details-buttons"></div>');
-    var jobj = container.children().last();
+    var details = $('<div/>', {
+        class: 'details'
+    }).appendTo(container);
+
+    details.append('<div class="details-buttons"></div>');
+    var jobj = details.children().last();
     jobj.append('<a class="details-reset" href="jslink">Reset</a>');
     jobj.append('<a class="details-update" href="jslink">Update</a>');
 
-    container.append('<hr />');
+    details.append('<hr />');
 
     for (var i = 0; i < dls.length; ++i) {
         var d = dls[i];
-        ipa_generate_dl(container.children().last(), d[0], d[1], d[2]);
+        ipa_generate_dl(details.children().last(), d[0], d[1], d[2]);
     }
 
-    container.append('<div class="details-back"></div>');
-    var jobj = container.children().last();
+    details.append('<div class="details-back"></div>');
+    var jobj = details.children().last();
     jobj.append('<a href="#details-viewtype">Back to Top</a>');
 }
 
@@ -87,8 +91,10 @@ function ipa_generate_dl(jobj, id, name, dts)
     jobj.after('<hr />');
 }
 
-function ipa_details_load(obj_name, pkey, on_win, on_fail, sampleData)
+function ipa_details_load(jobj, pkey, on_win, on_fail)
 {
+    var obj_name = jobj.attr('id');
+
     function load_on_win(data, text_status, xhr) {
         if (on_win)
             on_win(data, text_status, xhr);
@@ -103,14 +109,17 @@ function ipa_details_load(obj_name, pkey, on_win, on_fail, sampleData)
     function load_on_fail(xhr, text_status, error_thrown) {
         if (on_fail)
             on_fail(xhr, text_status, error_thrown);
+
+        var details = $('.details', jobj).empty();
+        details.append('<p>Error: '+error_thrown.name+'</p>');
+        details.append('<p>'+error_thrown.message+'</p>');
     };
 
     if (!pkey)
         return;
 
     ipa_cmd(
-        'show', [pkey], {all: true}, load_on_win, load_on_fail,
-        obj_name, sampleData
+        'show', [pkey], {all: true}, load_on_win, load_on_fail, obj_name
     );
 }
 
diff --git a/install/static/entity.js b/install/static/entity.js
index 7fb19fc..7b82c06 100644
--- a/install/static/entity.js
+++ b/install/static/entity.js
@@ -83,7 +83,7 @@ function ipa_entity_setup(jobj)
         }).appendTo($( "div#" + obj_name + " > div.search-controls"));
 
         if (typeof filter != 'undefined')
-            search_load(obj_name, filter, null, null);
+            search_load(jobj, filter, null, null);
     };
 
     function setup_details_facet() {
@@ -92,8 +92,9 @@ function ipa_entity_setup(jobj)
         ipa_details_create(obj_name, ipa_entity_details_list[obj_name], jobj);
         jobj.find('.details-reset').click(reset_on_click);
         jobj.find('.details-update').click(update_on_click);
+
         if (pkey)
-            ipa_details_load(obj_name, pkey, null, null);
+            ipa_details_load(jobj, pkey, null, null);
     };
 
     function setup_associate_facet() {
diff --git a/install/static/ipa.js b/install/static/ipa.js
index 6000fb7..dbd850b 100644
--- a/install/static/ipa.js
+++ b/install/static/ipa.js
@@ -30,7 +30,7 @@ var ipa_ajax_options = {
     contentType: 'application/json',
     dataType: 'json',
     async: true,
-    processData: false,
+    processData: false
 };
 
 /* JSON-RPC ID counter */
@@ -74,6 +74,27 @@ function ipa_init(url, use_static_files, on_win, on_error)
  *   objname - name of an IPA object (optional) */
 function ipa_cmd(name, args, options, win_callback, fail_callback, objname)
 {
+    function ipa_error_handler(xhr, text_status, error_thrown) {
+        var dialog = $('<div></div>');
+        dialog.attr('title', 'Error: '+error_thrown.name);
+        dialog.append('<p>'+error_thrown.message+'</p>');
+
+        dialog.dialog({
+            modal: true,
+            width: 400,
+            buttons: {
+                'Retry': function() {
+                    dialog.dialog('close');
+                    ipa_cmd(name, args, options, win_callback, fail_callback, objname);
+                },
+                'Cancel': function() {
+                    dialog.dialog('close');
+                    fail_callback(xhr, text_status, error_thrown);
+                }
+            }
+        });
+    };
+
     id = ipa_jsonrpc_id++;
     if (objname)
         name = objname + '_' + name;
@@ -89,14 +110,14 @@ function ipa_cmd(name, args, options, win_callback, fail_callback, objname)
     var data = {
         method: name,
         params: [args, options],
-        id: id,
+        id: id
     };
 
     var request = {
         url: url,
         data: JSON.stringify(data),
         success: win_callback,
-        error: fail_callback,
+        error: ipa_error_handler
     };
 
     $.ajax(request);
@@ -163,4 +184,3 @@ function ipa_get_member_attribute(obj_name, member)
 
     return null;
 }
-
diff --git a/install/static/navigation.js b/install/static/navigation.js
index 683c872..7972f37 100644
--- a/install/static/navigation.js
+++ b/install/static/navigation.js
@@ -61,9 +61,7 @@ function nav_generate_tabs(nls, container, tabclass, depth)
         var div = nav_create_tab_div(n[0]);
         container.append(div);
 
-        if (typeof n[2] == 'function') {
-            n[2](div);
-        } else if (n[2].length) {
+        if (typeof n[2] != 'function' && n[2].length) {
             nav_generate_tabs(n[2], div, tabclass, depth +1 );
         }
     }
diff --git a/install/static/search.js b/install/static/search.js
index 5e5be8f..59caf71 100644
--- a/install/static/search.js
+++ b/install/static/search.js
@@ -52,13 +52,19 @@ function search_create(obj_name, scl, container)
     jobj.children().last().click(find_on_click);
     div.append('<span class="search-buttons"></span>');
 
-    container.append('<table class="search-table"></table>');
-    jobj = container.children().last();
-    jobj.append('<thead><tr></tr></thead>');
-    jobj.append('<tbody></tbody>');
-    jobj.append('<tfoot></tfoot>');
+    var search_results = $('<div/>', {
+        class: 'search-results'
+    }).appendTo(container);
 
-    var tr = jobj.find('tr');
+    var search_table = $('<table/>', {
+        class: 'search-table'
+    }).appendTo(search_results);
+
+    search_table.append('<thead><tr></tr></thead>');
+    search_table.append('<tbody></tbody>');
+    search_table.append('<tfoot></tfoot>');
+
+    var tr = search_table.find('tr');
     for (var i = 0; i < scl.length; ++i) {
         var c = scl[i];
         search_insert_th(tr, obj_name, c[0], c[1], c[2]);
@@ -85,23 +91,29 @@ function search_insert_th(jobj, obj_name, attr, name, render_call)
     jobj.append(th);
 }
 
-function search_load(obj_name, criteria, on_win, on_fail)
+function search_load(jobj, criteria, on_win, on_fail)
 {
-    function load_on_win(data, text_status, xhr) {
+    var obj_name = jobj.attr('id');
+
+    function search_on_success(data, text_status, xhr) {
+        if (on_win)
+            on_win(data, text_status, xhr);
         if (data.error)
             return;
         search_display(obj_name, data);
-        if (on_win)
-            on_win(data, text_status, xhr);
     };
 
-    function load_on_fail(xhr, text_status, error_thrown) {
+    function search_on_error(xhr, text_status, error_thrown) {
         if (on_fail)
             on_fail(xhr, text_status, error_thrown);
-    };
+
+        var search_results = $('.search-results', jobj);
+        search_results.append('<p>Error: '+error_thrown.name+'</p>');
+        search_results.append('<p>'+error_thrown.message+'</p>');
+    }
 
     ipa_cmd(
-      'find', [criteria], {all: true}, load_on_win, load_on_fail, obj_name
+      'find', [criteria], {all: true}, search_on_success, search_on_error, obj_name
     );
 }
 
diff --git a/install/static/webui.js b/install/static/webui.js
index aa17b41..03c7b2f 100644
--- a/install/static/webui.js
+++ b/install/static/webui.js
@@ -72,6 +72,7 @@ $(function() {
             var navigation = $('#navigation');
             nav_create(nav_tabs_lists, navigation, 'tabs');
             nav_select_tabs(nav_tabs_lists, navigation);
+            update_tabs(nav_tabs_lists, navigation);
 
             $('#login_header').html(ipa_messages.login.header);
         }else{
@@ -80,19 +81,16 @@ $(function() {
     };
 
     function init_on_win(data, text_status, xhr) {
-        ipa_cmd('user_find', [], {"whoami":"true","all":"true"}, whoami_on_win,
-            function(xhr, options, thrownError) {
-                alert("Error: "+thrownError);
-            },
-            null
-        );
+        ipa_cmd('user_find', [], {"whoami":"true","all":"true"}, whoami_on_win, init_on_error, null);
     };
 
-    ipa_init(null, null, init_on_win,
-        function(xhr, options, thrownError) {
-            alert("Error: "+thrownError);
-        }
-    );
+    function init_on_error(xhr, text_status, error_thrown) {
+        var navigation = $('#navigation').empty();
+        navigation.append('<p>Error: '+error_thrown.name+'</p>');
+        navigation.append('<p>'+error_thrown.message+'</p>');
+    }
+
+    ipa_init(null, null, init_on_win, init_on_error);
 });
 
 /* use this to track individual changes between two hashchange events */
@@ -103,11 +101,23 @@ function window_hashchange(evt)
 {
     var navigation = $('#navigation');
     nav_select_tabs(nav_tabs_lists, navigation);
+    update_tabs(nav_tabs_lists, navigation);
+}
+
+function update_tabs(nls, navigation)
+{
+    var selected1 = navigation.tabs('option', 'selected');
+    for (var i = 0; i < nls.length; ++i) {
+        if (i != selected1) continue;
+
+        var t = nls[i];
+        var tabs = $('#'+t[0]);
+        var selected2 = tabs.tabs('option', 'selected');
 
-    for (var i = 0; i < nav_tabs_lists.length; ++i) {
-        var t = nav_tabs_lists[i];
         if (typeof t[2] != 'function' && t[2].length) {
             for (var j = 0; j < t[2].length; ++j) {
+                if (j != selected2) continue;
+
                 var tt = t[2][j];
                 var obj_name = tt[0];
                 var entity_setup = tt[2];
@@ -115,36 +125,42 @@ function window_hashchange(evt)
 
                 var state = obj_name + '-facet';
                 var facet = $.bbq.getState(state, true) || 'search';
-                var last_facet = window_hash_cache[state] || 'search';
+                var last_facet = window_hash_cache[state];
+
                 if (facet != last_facet) {
                     entity_setup(div);
-                    continue;
-                }
+                    window_hash_cache[state] = facet;
 
-                if (facet == 'search') {
+                } else if (facet == 'search') {
                     state = obj_name + '-filter';
                     var filter = $.bbq.getState(state, true);
                     var last_filter = window_hash_cache[state];
-                    if (filter != last_filter)
+                    if (filter != last_filter) {
                         entity_setup(div);
+                        window_hash_cache[state] = filter;
+                    }
+
                 } else if (facet == 'details') {
                     state = obj_name + '-pkey';
                     var pkey = $.bbq.getState(state, true);
                     var last_pkey = window_hash_cache[state];
-                    if (pkey != last_pkey)
+                    if (pkey != last_pkey) {
                         entity_setup(div);
+                        window_hash_cache[state] = pkey;
+                    }
+
                 } else if (facet == 'associate') {
                     state = obj_name + '-enroll';
                     var enroll = $.bbq.getState(state, true);
                     var last_enroll = window_hash_cache[state];
-                    if (enroll != last_enroll)
+                    if (enroll != last_enroll) {
                         entity_setup(div);
+                        window_hash_cache[state] = enroll;
+                    }
                 }
             }
         }
     }
-
-    window_hash_cache = $.bbq.getState();
 }
 
 /* builder function for unimplemented tab content */
-- 
1.6.6.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to