From 9c502641b5f7bf613eb9dbd4be21fbaf92312267 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Mon, 15 Nov 2010 11:10:55 -0600 Subject: HBAC details page enhancement The HBAC details page has been enhanced to support Undo and Reset operations. The functionality is implemented in the base widget class so the behavior will be more consistent across widgets. A tag now used to define the field boundary in the HTML doc. The tag contains the visual representation of the field which include the input tag and optionally the undo link. The Update method on HBAC details page has been modified so that it executes several operations using a batch command. The operations being executed depends on the changes made to the fields. These operations may include: - removing access time if access time is changed to any time - removing memberships if member category is changed to all - modifying rule attributes if description or rule type is changed - enabling/disabling the rule if rule status is changed The behavior of the Add & Remove buttons also has been changed such that it adjust the category attribute properly in addition to adding the memberships using batch command. For example, if category is initially set to all, adding a new member will also change the category to empty. The ipa_command have been modified to store the on_success and on_error handlers as properties. When the command is executed as a part of batch operation, the result of each command will be passed to the appropriate handler. The unit tests and test data have been updated as well. --- install/static/associate.js | 73 +- install/static/details.js | 256 ++++--- install/static/entity.js | 13 +- install/static/group.js | 8 +- install/static/hbac.js | 779 +++++++++++++++------ install/static/hbacsvc.js | 57 +- install/static/hbacsvcgroup.js | 57 +- install/static/ipa.js | 110 ++- .../layouts/default/hbac-details-accesstime.html | 67 +- .../layouts/default/hbac-details-general.html | 24 +- .../static/layouts/default/hbac-details-host.html | 15 +- .../layouts/default/hbac-details-service.html | 15 +- .../layouts/default/hbac-details-sourcehost.html | 15 +- .../static/layouts/default/hbac-details-user.html | 15 +- install/static/policy.js | 4 +- install/static/search.js | 67 +- install/static/serverconfig.js | 2 + install/static/service.js | 46 +- install/static/test/data/hbac_mod.json | 66 +- install/static/test/data/hbac_show.json | 31 +- install/static/test/details_tests.js | 43 +- install/static/widget.js | 307 +++++--- 22 files changed, 1360 insertions(+), 710 deletions(-) (limited to 'install/static') diff --git a/install/static/associate.js b/install/static/associate.js index 641409a8f..7dd81caec 100644 --- a/install/static/associate.js +++ b/install/static/associate.js @@ -244,7 +244,6 @@ function ipa_association_widget(spec) { that.other_entity = spec.other_entity; that.superior_create = that.superior('create'); - that.superior_setup = that.superior('setup'); that.create = function(container) { @@ -258,25 +257,42 @@ function ipa_association_widget(spec) { that.superior_create(container); - var div = $('#'+that.id, container); - var buttons = $('').appendTo($('.action-panel')); //TODO replace with ipa_button + var ul = $('.action-panel ul'); + var li = $('
  • ').appendTo(ul); + // creating generic buttons for layout $('', { 'type': 'button', 'name': 'remove', 'value': IPA.messages.button.remove - }).appendTo(buttons); + }).appendTo(li); $('', { 'type': 'button', 'name': 'add', 'value': IPA.messages.button.enroll - }).appendTo(buttons); + }).appendTo(li); }; that.setup = function(container) { - that.superior_setup(container); + that.table_setup(container); + + // replacing generic buttons with ipa_button and setting click handler + var action_panel = $('.action-panel'); + var button = $('input[name=remove]', action_panel); + button.replaceWith(ipa_button({ + 'label': button.val(), + 'icon': 'ui-icon-trash', + 'click': function() { that.remove(that.container); } + })); + + button = $('input[name=add]', action_panel); + button.replaceWith(ipa_button({ + 'label': button.val(), + 'icon': 'ui-icon-plus', + 'click': function() { that.add(that.container) } + })); var entity = IPA.get_entity(that.entity_name); var association = entity.get_association(that.other_entity); @@ -308,18 +324,18 @@ function ipa_association_widget(spec) { 'associator': that.associator, 'method': that.add_method, 'on_success': function() { - that.refresh(container); + that.refresh(that.container); dialog.close(); }, 'on_error': function() { - that.refresh(container); + that.refresh(that.container); dialog.close(); } }); dialog.init(); - dialog.open(container); + dialog.open(that.container); }; that.remove = function(container) { @@ -344,18 +360,18 @@ function ipa_association_widget(spec) { 'associator': that.associator, 'method': that.delete_method, 'on_success': function() { - that.refresh(container); + that.refresh(that.container); dialog.close(); }, 'on_error': function() { - that.refresh(container); + that.refresh(that.container); dialog.close(); } }); dialog.init(); - dialog.open(container); + dialog.open(that.container); }; that.refresh = function(container) { @@ -374,15 +390,15 @@ function ipa_association_widget(spec) { for (var i = 0; iError: '+error_thrown.name+'

    '); - div.append('

    '+error_thrown.title+'

    '); - div.append('

    '+error_thrown.message+'

    '); + var summary = $('span[name=summary]', that.tfoot).empty(); + summary.append('

    Error: '+error_thrown.name+'

    '); + summary.append('

    '+error_thrown.title+'

    '); + summary.append('

    '+error_thrown.message+'

    '); } var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; @@ -407,10 +423,21 @@ function ipa_association_facet(spec) { }; that.create = function(container) { + that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; that.other_entity = $.bbq.getState(that.entity_name + '-enroll', true) || ''; + var label = IPA.metadata[that.other_entity] ? IPA.metadata[that.other_entity].label : that.other_entity; + + that.table = ipa_association_widget({ + 'id': that.entity_name+'-'+that.other_entity, + 'name': 'association', + 'label': label, + 'entity_name': that.entity_name, + 'other_entity': that.other_entity + }); + //TODO I18N var header_message = that.other_entity + '(s) enrolled in ' + that.entity_name + ' ' + that.pkey; @@ -427,13 +454,17 @@ function ipa_association_facet(spec) { 'other_entity': that.other_entity }); - that.table.create(container); + var span = $('', { 'name': 'association' }).appendTo(container); + that.table.create(span); }; - that.setup = function(container, unspecified) { - that.table.setup(container); - that.table.refresh(container); + that.setup = function(container) { + + var span = $('span[name=association]', container); + + that.table.setup(span); + that.table.refresh(); }; return that; diff --git a/install/static/details.js b/install/static/details.js index 612716c35..49957a56d 100644 --- a/install/static/details.js +++ b/install/static/details.js @@ -40,29 +40,26 @@ function ipa_details_field(spec) { var that = ipa_widget(spec); that.create = spec.create || create; - that.setup = spec.setup || setup; that.load = spec.load || load; that.save = spec.save || save; function create(container) { - var dl = $('dl', container); - var title = that.name; var label = ''; + var param_info = ipa_get_param_info(that.entity_name, that.name); if (param_info) label = param_info['label']; + if (!label) label = that.label; + $('
    ', { id: that.name, title: title, html: label + ':' - }).appendTo(dl); - } - - function setup(container) { + }).appendTo(container); } function load(container, result) { @@ -129,10 +126,9 @@ function ipa_details_field(spec) { } function save(container) { - var field = this; var values = []; - var dd = $('dd[title='+field.name+']', container); + var dd = $('dd[title='+that.name+']', container); dd.each(function () { var input = $('input', $(this)); if (!input.length) return; @@ -156,15 +152,12 @@ function ipa_details_section(spec){ spec = spec || {}; var that = {}; + that.name = spec.name || ''; that.label = spec.label || ''; that.template = spec.template; that._entity_name = spec.entity_name; - that.setup = spec.setup || ipa_details_section_setup; - that.create = spec.create || ipa_details_section_create; - that.load = spec.load || ipa_details_section_load; - that.fields = []; that.fields_by_name = {}; @@ -234,6 +227,126 @@ function ipa_details_section(spec){ } }; + that.create = function(container) { + + if (that.template) return; + + var fields = that.fields; + for (var i = 0; i < fields.length; ++i) { + var field = fields[i]; + + var span = $('', { 'name': field.name }).appendTo(container); + field.create(span); + } + }; + + that.setup = function(container) { + + this.container = container; + + if (that.template) return; + + var fields = that.fields; + for (var i = 0; i < fields.length; ++i) { + var field = fields[i]; + + var span = $('span[name='+field.name+']', this.container).first(); + field.setup(span); + } + }; + + that.load = function(result) { + + var fields = that.fields; + + if (that.template) { + var template = IPA.get_template(that.template); + this.container.load( + template, + function(data, text_status, xhr) { + for (var i = 0; i < fields.length; ++i) { + var field = fields[i]; + var span = $('span[name='+field.name+']', this.container).first(); + field.setup(span); + field.load(span, result); + } + } + ); + return; + } + + for (var j=0; j', { + 'id': that.name, + 'class': 'entryattrs' + }).appendTo(container); + + var fields = that.fields; + for (var i = 0; i < fields.length; ++i) { + var field = fields[i]; + + var span = $('', { 'name': field.name }).appendTo(dl); + field.create(span); + } + }; + + /* populate definition lists with the class 'entryattrs' with entry attributes + * + * The list has to be specially crafted for this function to work properly: + *
    tags should have the 'title' attribute set to an LDAP attribute name + * OR to a javascript function name prefixed with 'call_', which will be given + * the
    object and entry_attrs as arguments. + * Example: + *
    + *
    First Name:
    + *
    Some Attribute:
    + *
    + * + * arguments: + * result - 'result' field as returned by ipa *-show commnads + * (basically an associative array with attr:value pairs) */ + that.load = function(result) { + /* remove all
    tags i.e. all attribute values */ + $('dd', that.container).remove(); + + /* go through all
    tags and pair them with newly created
    s */ + that.section_load(result); + }; + // Deprecated: Used for backward compatibility only. function input(spec){ that.create_field(spec); @@ -247,7 +360,7 @@ function ipa_details_section(spec){ // Deprecated: Used for backward compatibility only. function ipa_stanza(spec) { - return ipa_details_section(spec); + return ipa_details_list_section(spec); } function ipa_details_facet(spec) { @@ -392,7 +505,8 @@ function ipa_details_create(container) } } -function ipa_details_setup(container, unspecified) { +function ipa_details_setup(container) { + var that = this; for (var i = 0; i < that.sections.length; ++i) { @@ -403,16 +517,17 @@ function ipa_details_setup(container, unspecified) { container ); - section.setup(div, unspecified); + section.setup(div); } } -function ipa_details_load(container, unspecified) { +function ipa_details_load(container) { var that = this; + var entity = IPA.get_entity(that.entity_name); that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; - if (!that.pkey && !unspecified) return; + if (!that.pkey && !entity.default_facet) return; function on_success(data, text_status, xhr) { var result = data.result.result; @@ -420,13 +535,7 @@ function ipa_details_load(container, unspecified) { ipa_details_cache[that.entity_name] = $.extend(true, {}, result); for (var i = 0; i < that.sections.length; ++i) { var section = that.sections[i]; - - var div = $( - '#'+that.entity_name+'-'+that.name+'-'+section.name, - container - ); - - section.load(div, result); + section.load(result); } } @@ -445,59 +554,6 @@ function ipa_details_load(container, unspecified) { ); } -function ipa_details_section_create(container) { - - var that = this; - if (that.template) return; - - var dl = $('
    ', { - 'id': that.name, - 'class': 'entryattrs' - }).appendTo(container); - - var fields = that.fields; - for (var i = 0; i < fields.length; ++i) { - var field = fields[i]; - field.create(container); - } -} - -function ipa_details_section_setup(container, unspecified) { - var that = this; - if (that.template) return; - - var fields = that.fields; - for (var i = 0; i < fields.length; ++i) { - var field = fields[i]; - field.setup(container); - } -} - -function ipa_details_section_load(container, result) { - var that = this; - var fields = that.fields; - - if (that.template) { - var template = IPA.get_template(that.template); - container.load( - template, - function(data, text_status, xhr) { - for (var i = 0; i < fields.length; ++i) { - var field = fields[i]; - field.setup(container); - field.load(container, result); - } - } - ); - return; - } - - for (var j=0; j tags should have the 'title' attribute set to an LDAP attribute name - * OR to a javascript function name prefixed with 'call_', which will be given - * the
    object and entry_attrs as arguments. - * Example: - *
    - *
    First Name:
    - *
    Some Attribute:
    - *
    - * - * arguments: - * result - 'result' field as returned by ipa *-show commnads - * (basically an associative array with attr:value pairs) */ -function ipa_details_display(container, result) +function ipa_details_display(result) { var facet = this; - /* remove all
    tags i.e. all attribute values */ - $('dd', container).remove(); - - /* go through all
    tags and pair them with newly created
    s */ for (var i=0; i', { - 'class': 'first', 'title': field_name }).append(content); @@ -783,13 +817,17 @@ function _ipa_create_text_input(attr, value, param_info, rights) function ipa_details_reset(container) { - var facet = this; - var entity_name = facet.entity_name; + var that = this; + var entity_name = that.entity_name; if (ipa_details_cache[entity_name]){ - facet.display(container, ipa_details_cache[entity_name]); + that.display(ipa_details_cache[entity_name]); } + for (var i=0; i', { "class":"action-panel", - html: $('

    Actions

    '), + html: $('

    Actions

    ') }); var ul = $('