diff options
Diffstat (limited to 'install/static')
-rw-r--r-- | install/static/associate.js | 42 | ||||
-rw-r--r-- | install/static/details.js | 29 | ||||
-rw-r--r-- | install/static/entity.js | 5 | ||||
-rw-r--r-- | install/static/ipa.js | 38 | ||||
-rw-r--r-- | install/static/navigation.js | 64 | ||||
-rw-r--r-- | install/static/search.js | 38 | ||||
-rw-r--r-- | install/static/test/ipa_tests.html | 3 | ||||
-rw-r--r-- | install/static/test/ipa_tests.js | 201 | ||||
-rw-r--r-- | install/static/test/navigation_tests.js | 12 | ||||
-rw-r--r-- | install/static/webui.js | 67 |
10 files changed, 380 insertions, 119 deletions
diff --git a/install/static/associate.js b/install/static/associate.js index 207c745c3..c3453e965 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 f68c77324..4e37ed696 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 ); } @@ -301,7 +310,7 @@ var _ipa_param_type_2_handler_map = { 'Str': _ipa_create_text_input, 'Int': _ipa_create_text_input, 'Bool': _ipa_create_text_input, - 'List': _ipa_create_text_input, + 'List': _ipa_create_text_input }; /* create an HTML element for displaying/editing an attribute diff --git a/install/static/entity.js b/install/static/entity.js index 7fb19fc79..7b82c06e3 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 6000fb73e..25a3f1bb7 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 */ @@ -40,6 +40,7 @@ var ipa_jsonrpc_id = 0; var ipa_messages = {}; var ipa_objs = {}; +var ipa_dialog = $('<div/>', {id: 'ipa_dialog'}); /* initialize the IPA JSON-RPC helper * arguments: @@ -74,9 +75,33 @@ 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) { + ipa_dialog.empty(); + ipa_dialog.attr('title', 'Error: '+error_thrown.name); + ipa_dialog.append('<p>'+error_thrown.message+'</p>'); + + ipa_dialog.dialog({ + modal: true, + width: 400, + buttons: { + 'Retry': function() { + ipa_dialog.dialog('close'); + ipa_cmd(name, args, options, win_callback, fail_callback, objname); + }, + 'Cancel': function() { + ipa_dialog.dialog('close'); + fail_callback(xhr, text_status, error_thrown); + } + } + }); + }; + id = ipa_jsonrpc_id++; + + var method_name = name; + if (objname) - name = objname + '_' + name; + method_name = objname + '_' + name; var url = ipa_json_url; @@ -84,19 +109,19 @@ function ipa_cmd(name, args, options, win_callback, fail_callback, objname) url = IPA_DEFAULT_JSON_URL; if (ipa_use_static_files) - url += '/' + name + '.json'; + url += '/' + method_name + '.json'; var data = { - method: name, + method: 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 +188,3 @@ function ipa_get_member_attribute(obj_name, member) return null; } - diff --git a/install/static/navigation.js b/install/static/navigation.js index 169729ba0..3aa49fe2b 100644 --- a/install/static/navigation.js +++ b/install/static/navigation.js @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* use this to track individual changes between two hashchange events */ +var window_hash_cache = {}; function nav_create(nls, container, tabclass) { @@ -38,6 +40,8 @@ function nav_create(nls, container, tabclass) return true; } }); + + nav_update_tabs(nls, container); } function nav_generate_tabs(nls, container, tabclass, depth) @@ -62,9 +66,7 @@ function nav_generate_tabs(nls, container, tabclass, depth) var div = nav_create_tab_div(n.name); container.append(div); - if (n.setup) { - n.setup(div); - } else if (n.children) { + if (n.children) { nav_generate_tabs(n.children, div, tabclass, depth +1 ); } } @@ -103,3 +105,59 @@ function nav_select_tabs(nls, container) } } } + +function nav_update_tabs(nls, container) +{ + nav_select_tabs(nls, container); + + var index1 = container.tabs('option', 'selected'); + if (index1 >= nls.length) return; + + var tab1 = nls[index1]; + if (!tab1.children) return; + + var div1 = $('#' + tab1.name); + var index2 = div1.tabs('option', 'selected'); + if (index2 >= tab1.children.length) return; + + var tab2 = tab1.children[index2]; + var obj_name = tab2.name; + var entity_setup = tab2.setup; + var div2 = $('#' + tab2.name); + + var state = obj_name + '-facet'; + var facet = $.bbq.getState(state, true) || 'search'; + var last_facet = window_hash_cache[state]; + + if (facet != last_facet) { + entity_setup(div2); + window_hash_cache[state] = facet; + + } 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) return; + + entity_setup(div2); + 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) return; + + entity_setup(div2); + 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) return; + + entity_setup(div2); + window_hash_cache[state] = enroll; + } +} diff --git a/install/static/search.js b/install/static/search.js index 5e5be8fa0..59caf71f0 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/test/ipa_tests.html b/install/static/test/ipa_tests.html index 3031f2310..dfe2720a5 100644 --- a/install/static/test/ipa_tests.html +++ b/install/static/test/ipa_tests.html @@ -3,8 +3,11 @@ <head> <title>Core Test Suite</title> <link rel="stylesheet" href="qunit.css" type="text/css" media="screen"> + <link rel="stylesheet" type="text/css" href="../jquery-ui.css" /> + <script type="text/javascript" src="qunit.js"></script> <script type="text/javascript" src="../jquery.js"></script> + <script type="text/javascript" src="../jquery-ui.js"></script> <script type="text/javascript" src="../ipa.js"></script> <script type="text/javascript" src="ipa_tests.js"></script> </head> diff --git a/install/static/test/ipa_tests.js b/install/static/test/ipa_tests.js index 8dbdd62d5..8617a8439 100644 --- a/install/static/test/ipa_tests.js +++ b/install/static/test/ipa_tests.js @@ -92,3 +92,204 @@ test("Testing ipa_get_member_attribute().", function() { "ipa_get_member_attribute(null, \"group\")" ); }); + +test("Testing successful ipa_cmd().", function() { + + var method = 'method'; + var args = ['arg1', 'arg2', 'arg3']; + var options = { + opt1: 'val1', + opt2: 'val2', + opt3: 'val3' + }; + var object = 'object'; + + var success_handler_counter = 0; + var error_handler_counter = 0; + + function success_handler(data, status, xhr) { + success_handler_counter++; + } + + function error_handler(xhr, text_status, error_thrown) { + error_handler_counter++; + } + + var orig = $.ajax; + + var xhr = {}; + var text_status = null; + var error_thrown = {name:'ERROR', message:'An error has occured'}; + + var ajax_counter = 0; + + $.ajax = function(request) { + ajax_counter++; + + equals( + request.url, "data/"+object+"_"+method+".json", + "Checking request.url" + ); + + var data = JSON.parse(request.data); + + equals( + data.method, object+'_'+method, + "Checking method" + ); + + same( + data.params, [args, options], + "Checking parameters" + ); + + request.success(xhr, text_status, error_thrown); + }; + + ipa_cmd(method, args, options, success_handler, error_handler, object); + + equals( + ajax_counter, 1, + "Checking ajax invocation counter" + ); + + var dialog = ipa_dialog.parent('.ui-dialog'); + + ok( + !dialog.length, + "The dialog box is not created." + ); + + ok( + success_handler_counter == 1 && error_handler_counter == 0, + "Only the success handler is called." + ); + + $.ajax = orig; +}); + +test("Testing unsuccessful ipa_cmd().", function() { + + var method = 'method'; + var args = ['arg1', 'arg2', 'arg3']; + var options = { + opt1: 'val1', + opt2: 'val2', + opt3: 'val3' + }; + var object = 'object'; + + var success_handler_counter = 0; + var error_handler_counter = 0; + + function success_handler(data, status, xhr) { + success_handler_counter++; + } + + function error_handler(xhr, text_status, error_thrown) { + error_handler_counter++; + } + + var orig = $.ajax; + + var xhr = {}; + var text_status = null; + var error_thrown = {name:'ERROR', message:'An error has occured'}; + + var ajax_counter = 0; + + $.ajax = function(request) { + ajax_counter++; + + equals( + request.url, "data/"+object+"_"+method+".json", + "Checking request.url" + ); + + var data = JSON.parse(request.data); + + equals( + data.method, object+'_'+method, + "Checking method" + ); + + same( + data.params, [args, options], + "Checking parameters" + ); + + request.error(xhr, text_status, error_thrown); + }; + + ipa_cmd(method, args, options, success_handler, error_handler, object); + + var dialog = ipa_dialog.parent('.ui-dialog'); + + equals( + ajax_counter, 1, + "Checking ajax invocation counter" + ); + + ok( + dialog.length == 1 && ipa_dialog.dialog('isOpen'), + "The dialog box is created and open." + ); + + ok( + success_handler_counter == 0 && error_handler_counter == 0, + "Initially none of the handlers are called." + ); + + // search the retry button from the beginning + var retry = $('button', dialog).first(); + retry.trigger('click'); + + equals( + ajax_counter, 2, + "Checking ajax invocation counter" + ); + + ok( + success_handler_counter == 0 && error_handler_counter == 0, + "After 1st retry, none of the handlers are called." + ); + + // search the retry button from the beginning again because the dialog + // has been recreated + dialog = ipa_dialog.parent('.ui-dialog'); + retry = $('button', dialog).first(); + retry.trigger('click'); + + equals( + ajax_counter, 3, + "Checking ajax invocation counter" + ); + + ok( + success_handler_counter == 0 && error_handler_counter == 0, + "After 2nd retry, none of the handlers are called." + ); + + // search the cancel button from the beginning because the dialog has + // been recreated + dialog = ipa_dialog.parent('.ui-dialog'); + var cancel = $('button', dialog).first().next(); + cancel.trigger('click'); + + equals( + ajax_counter, 3, + "Checking ajax invocation counter" + ); + + ok( + !ipa_dialog.dialog('isOpen'), + "After cancel, the dialog box is closed." + ); + + ok( + success_handler_counter == 0 && error_handler_counter == 1, + "Only the error handler is called." + ); + + $.ajax = orig; +}); diff --git a/install/static/test/navigation_tests.js b/install/static/test/navigation_tests.js index 16b3ae925..4144e81a4 100644 --- a/install/static/test/navigation_tests.js +++ b/install/static/test/navigation_tests.js @@ -41,17 +41,17 @@ test("Testing nav_create().", function() { } ipa_objs= {}; - var navigation = $('<div id="navigation"/>'); + var navigation = $('<div id="navigation"/>').appendTo(document.body); var user_mock_called = false; var group_mock_called = false; nav_create(mock_tabs_lists, navigation, 'tabs') - ok(user_mock_called, "mock setup was called"); - ok(group_mock_called, "mock setup was called"); + ok(user_mock_called, "mock user setup was called"); + ok(!group_mock_called, "mock group setup was not called because the tab is inactive"); same( navigation[0].children.length, 2, "Two Child tabs"); same( navigation[0].children[1].id, 'identity', "Identity Tab"); same( navigation[0].children[1].children[1].id, 'user', "User Tab"); same( navigation[0].children[1].children[2].id, 'group', "User Tab"); - + navigation.remove(); }); test("Testing nav_select_tabs().", function() { @@ -64,12 +64,14 @@ test("Testing nav_select_tabs().", function() { {name:'two', label:'Two', setup: function (){}}, ]}]; - var navigation = $('<div id="navigation"/>'); + var navigation = $('<div id="navigation"/>').appendTo(document.body); nav_create(mock_tabs_lists, navigation, 'tabs') $.bbq.pushState({"identity":2}); nav_select_tabs(mock_tabs_lists, navigation); same( navigation[0].children[1].children[2].id, 'two', "Tab two"); + $.bbq.removeState(["identity"]); + navigation.remove(); }); diff --git a/install/static/webui.js b/install/static/webui.js index 331ec82e7..ac28412de 100644 --- a/install/static/webui.js +++ b/install/static/webui.js @@ -75,7 +75,6 @@ $(function() { var navigation = $('#navigation'); nav_create(nav_tabs_lists, navigation, 'tabs'); - nav_select_tabs(nav_tabs_lists, navigation); $('#login_header').html(ipa_messages.login.header); }else{ @@ -84,71 +83,23 @@ $(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>'); + } -/* use this to track individual changes between two hashchange events */ -var window_hash_cache = {}; + ipa_init(null, null, init_on_win, init_on_error); +}); /* main loop (hashchange event handler) */ function window_hashchange(evt) { var navigation = $('#navigation'); - nav_select_tabs(nav_tabs_lists, navigation); - - for (var i = 0; i < nav_tabs_lists.length; ++i) { - var t = nav_tabs_lists[i]; - if (!(t.setup) && t.children) { - for (var j = 0; j < t.children.length; ++j) { - var tt = t.children[j]; - var obj_name = tt.name; - var entity_setup = tt.setup; - var div = $('#' + tt.name); - - var state = obj_name + '-facet'; - var facet = $.bbq.getState(state, true) || 'search'; - var last_facet = window_hash_cache[state] || 'search'; - if (facet != last_facet) { - entity_setup(div); - continue; - } - - if (facet == 'search') { - state = obj_name + '-filter'; - var filter = $.bbq.getState(state, true); - var last_filter = window_hash_cache[state]; - if (filter != last_filter) - entity_setup(div); - } 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) - entity_setup(div); - } 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) - entity_setup(div); - } - } - } - } - - window_hash_cache = $.bbq.getState(); + nav_update_tabs(nav_tabs_lists, navigation); } /* builder function for unimplemented tab content */ |