Hi,

Please review the attached patch. Thanks!

https://fedorahosted.org/reviewboard/r/112/

The enrollment dialog has been modified to use scrollable tables that
supports multiple columns to display the search results and selected
entries. The columns are specified by calling create_adder_column()
on the association facet. By default the tables will use only one
column which is to display the primary keys.

The following enrollment dialogs have been modified to use multiple
columns:
 - Group's member_user
 - Service's managedby_host
 - HBAC Service Group's member_hbacsvc
 - SUDO Command Group's member_sudocmd

The ipa_association_table_widget's add() and remove() have been moved
into ipa_association_facet so they can be customized by facet's
subclass. The ipa_table's add_row() has been renamed to add_record().

Some old code has been removed from ipa_facet_create_action_panel().
The code was used to generate association links from a single facet.
It's no longer needed because now each association has its own facet.

The test data has been updated. The IPA.nested_tabs() has been fixed
to return the entity itself if IPA.tab_set is not defined. This is
needed to pass unit test.

--
Endi S. Dewata
From ef4210e6c4d93c2d2b6eebec89e030d26d9aa39c Mon Sep 17 00:00:00 2001
From: Endi S. Dewata <edew...@redhat.com>
Date: Wed, 1 Dec 2010 14:51:39 -0600
Subject: [PATCH] Multicolumn enrollment dialog

The enrollment dialog has been modified to use scrollable tables that
supports multiple columns to display the search results and selected
entries. The columns are specified by calling create_adder_column()
on the association facet. By default the tables will use only one
column which is to display the primary keys.

The following enrollment dialogs have been modified to use multiple
columns:
 - Group's member_user
 - Service's managedby_host
 - HBAC Service Group's member_hbacsvc
 - SUDO Command Group's member_sudocmd

The ipa_association_table_widget's add() and remove() have been moved
into ipa_association_facet so they can be customized by facet's
subclass. The ipa_table's add_row() has been renamed to add_record().

Some old code has been removed from ipa_facet_create_action_panel().
The code was used to generate association links from a single facet.
It's no longer needed because now each association has its own facet.

The test data has been updated. The IPA.nested_tabs() has been fixed
to return the entity itself if IPA.tab_set is not defined. This is
needed to pass unit test.
---
 install/static/associate.js                |  245 ++++++++++++++++------------
 install/static/entity.js                   |   22 +--
 install/static/group.js                    |   13 ++
 install/static/hbac.js                     |    2 +-
 install/static/hbacsvcgroup.js             |   22 +++-
 install/static/ipa.css                     |    2 +-
 install/static/rule.js                     |    2 +-
 install/static/search.js                   |    2 +-
 install/static/service.js                  |   13 ++
 install/static/sudocmdgroup.js             |   22 +++-
 install/static/test/data/hbacsvc_find.json |   29 +++-
 install/static/widget.js                   |  208 ++++++++++++++++--------
 12 files changed, 388 insertions(+), 194 deletions(-)

diff --git a/install/static/associate.js b/install/static/associate.js
index fbd1c63c98bbff0186e9cb17de3148514fb1a02e..a6edf748f7dc9b54292f7b8b469ce624e0ad5f8e 100644
--- a/install/static/associate.js
+++ b/install/static/associate.js
@@ -152,9 +152,13 @@ function ipa_association_adder_dialog(spec) {
             var pkey_name = IPA.metadata[that.other_entity].primary_key;
             that.create_column({
                 name: pkey_name,
-                primary_key: true
+                label: IPA.metadata[that.other_entity].label,
+                primary_key: true,
+                width: '200px'
             });
         }
+
+        that.adder_dialog_init();
     };
 
     that.search = function() {
@@ -170,7 +174,7 @@ function ipa_association_adder_dialog(spec) {
         }
 
         var filter = that.get_filter();
-        ipa_cmd('find', [filter], {}, on_success, null, that.other_entity);
+        ipa_cmd('find', [filter], {'all': true}, on_success, null, that.other_entity);
     };
 
     that.add = function() {
@@ -252,13 +256,11 @@ function ipa_association_table_widget(spec) {
     that.facet = spec.facet;
     that.other_entity = spec.other_entity;
 
-    that.superior_create = that.superior('create');
+    that.add = spec.add;
+    that.remove = spec.remove;
 
     that.create = function(container) {
 
-        that.member_attribute = ipa_get_member_attribute(
-            that.entity_name, that.other_entity);
-
         if (!that.columns.length) {
             var pkey_name = IPA.metadata[that.other_entity].primary_key;
 
@@ -290,7 +292,7 @@ function ipa_association_table_widget(spec) {
             };
         }
 
-        that.superior_create(container);
+        that.table_create(container);
 
         var action_panel = that.facet.get_action_panel();
         var li = $('.action-controls', action_panel);
@@ -320,94 +322,15 @@ function ipa_association_table_widget(spec) {
         button.replaceWith(ipa_button({
             'label': button.val(),
             'icon': 'ui-icon-trash',
-            'click': function() { that.remove(that.container); }
+            'click': function() { that.remove(); }
         }));
 
         button = $('input[name=add]', action_panel);
         button.replaceWith(ipa_button({
             'label': button.val(),
             'icon': 'ui-icon-plus',
-            'click': function() { that.add(that.container) }
+            'click': function() { that.add() }
         }));
-
-        var entity = IPA.get_entity(that.entity_name);
-        var association = entity.get_association(that.other_entity);
-
-        if (association && association.associator == 'serial') {
-            that.associator = serial_associator;
-        } else {
-            that.associator = bulk_associator;
-        }
-
-        that.add_method = association ? association.add_method : null;
-        that.delete_method = association ? association.delete_method : null;
-
-        that.add_method = that.add_method || "add_member";
-        that.delete_method = that.delete_method || "remove_member";
-    };
-
-    that.add = function(container) {
-
-        var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
-        var label = IPA.metadata[that.other_entity].label;
-        var title = 'Enroll '+that.entity_name+' '+pkey+' in '+label;
-
-        var dialog = ipa_association_adder_dialog({
-            'title': title,
-            'entity_name': that.entity_name,
-            'pkey': pkey,
-            'other_entity': that.other_entity,
-            'associator': that.associator,
-            'method': that.add_method,
-            'on_success': function() {
-                that.refresh();
-                dialog.close();
-            },
-            'on_error': function() {
-                that.refresh();
-                dialog.close();
-            }
-        });
-
-        dialog.init();
-
-        dialog.open(that.container);
-    };
-
-    that.remove = function(container) {
-
-        var values = that.get_selected_values();
-
-        if (!values.length) {
-            alert('Select '+that.label+' to be removed.');
-            return;
-        }
-
-        var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
-        var label = IPA.metadata[that.other_entity].label;
-        var title = 'Remove '+label+' from '+that.entity_name+' '+pkey;
-
-        var dialog = ipa_association_deleter_dialog({
-            'title': title,
-            'entity_name': that.entity_name,
-            'pkey': pkey,
-            'other_entity': that.other_entity,
-            'values': values,
-            'associator': that.associator,
-            'method': that.delete_method,
-            'on_success': function() {
-                that.refresh();
-                dialog.close();
-            },
-            'on_error': function() {
-                that.refresh();
-                dialog.close();
-            }
-        });
-
-        dialog.init();
-
-        dialog.open(that.container);
     };
 
     that.get_records = function(pkeys, on_success, on_error) {
@@ -443,13 +366,14 @@ function ipa_association_table_widget(spec) {
             that.tbody.empty();
 
             var pkeys = data.result.result[that.name];
+            if (!pkeys) return;
 
             if (that.columns.length == 1) { // show pkey only
                 var name = that.columns[0].name;
                 for (var i=0; i<pkeys.length; i++) {
                     var record = {};
                     record[name] = pkeys[i];
-                    that.add_row(record);
+                    that.add_record(record);
                 }
 
             } else { // get and show additional fields
@@ -459,7 +383,7 @@ function ipa_association_table_widget(spec) {
                         var results = data.result.results;
                         for (var i=0; i<results.length; i++) {
                             var record = results[i].result;
-                            that.add_row(record);
+                            that.add_record(record);
                         }
                     }
                 );
@@ -488,9 +412,16 @@ function ipa_association_facet(spec) {
 
     that.other_entity = spec.other_entity;
 
+    that.associator = spec.associator || bulk_associator;
+    that.add_method = spec.add_method || 'add_member';
+    that.delete_method = spec.delete_method || 'remove_member';
+
     that.columns = [];
     that.columns_by_name = {};
 
+    that.adder_columns = [];
+    that.adder_columns_by_name = {};
+
     that.get_column = function(name) {
         return that.columns_by_name[name];
     };
@@ -507,17 +438,66 @@ function ipa_association_facet(spec) {
         return column;
     };
 
+    that.get_adder_column = function(name) {
+        return that.adder_columns_by_name[name];
+    };
+
+    that.add_adder_column = function(column) {
+        column.entity_name = that.entity_name;
+        that.adder_columns.push(column);
+        that.adder_columns_by_name[column.name] = column;
+    };
+
+    that.create_adder_column = function(spec) {
+        var column = ipa_column(spec);
+        that.add_adder_column(column);
+        return column;
+    };
+
     that.is_dirty = function() {
         var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
         return pkey != that.pkey || other_entity != that.other_entity;
     };
 
+    that.init = function() {
+
+        var entity = IPA.get_entity(that.entity_name);
+        var association = entity.get_association(that.other_entity);
+
+        if (association) {
+            if (association.associator) {
+                that.associator = association.associator == 'serial' ? serial_associator : bulk_associator;
+            }
+
+            if (association.add_method) that.add_method = association.add_method;
+            if (association.delete_method) that.delete_method = association.delete_method;
+        }
+
+        var label = IPA.metadata[that.other_entity] ? IPA.metadata[that.other_entity].label : that.other_entity;
+
+        that.table = ipa_association_table_widget({
+            'id': that.entity_name+'-'+that.other_entity,
+            'name': that.name,
+            'label': label,
+            'entity_name': that.entity_name,
+            'other_entity': that.other_entity,
+            'facet': that
+        });
+
+        if (that.columns.length) {
+            that.table.set_columns(that.columns);
+        }
+
+        that.table.add = function() { that.add(); };
+        that.table.remove = function() { that.remove() };
+
+        that.facet_init();
+    };
+
     that.create = function(container) {
 
         that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
 
-        var label = IPA.metadata[that.other_entity] ? IPA.metadata[that.other_entity].label : that.other_entity;
-
         //TODO I18N
         var header_message = that.other_entity + '(s) enrolled in '  +
             that.entity_name + ' ' + that.pkey;
@@ -527,19 +507,6 @@ function ipa_association_facet(spec) {
             html: $('<h2/>',{ html:  header_message })
         }).appendTo(container);
 
-        that.table = ipa_association_table_widget({
-            'id': that.entity_name+'-'+that.other_entity,
-            'name': that.name,
-            'label': label,
-            'entity_name': that.entity_name,
-            'other_entity': that.other_entity,
-            'facet': that
-        });
-
-        if (that.columns.length) {
-            that.table.set_columns(that.columns);
-        }
-
         var span = $('<span/>', { 'name': 'association' }).appendTo(container);
 
         that.table.create(span);
@@ -554,6 +521,74 @@ function ipa_association_facet(spec) {
         that.table.setup(span);
     };
 
+    that.add = function() {
+
+        var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+        var label = IPA.metadata[that.other_entity] ? IPA.metadata[that.other_entity].label : that.other_entity;
+        var title = 'Enroll '+that.entity_name+' '+pkey+' in '+label;
+
+        var dialog = ipa_association_adder_dialog({
+            'title': title,
+            'entity_name': that.entity_name,
+            'pkey': pkey,
+            'other_entity': that.other_entity,
+            'associator': that.associator,
+            'method': that.add_method,
+            'on_success': function() {
+                that.refresh();
+                dialog.close();
+            },
+            'on_error': function() {
+                that.refresh();
+                dialog.close();
+            }
+        });
+
+        if (that.adder_columns.length) {
+            dialog.set_columns(that.adder_columns);
+        }
+
+        dialog.init();
+
+        dialog.open(that.container);
+    };
+
+    that.remove = function() {
+
+        var label = IPA.metadata[that.other_entity] ? IPA.metadata[that.other_entity].label : that.other_entity;
+        var values = that.table.get_selected_values();
+
+        if (!values.length) {
+            alert('Select '+label+' to be removed.');
+            return;
+        }
+
+        var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+        var title = 'Remove '+label+' from '+that.entity_name+' '+pkey;
+
+        var dialog = ipa_association_deleter_dialog({
+            'title': title,
+            'entity_name': that.entity_name,
+            'pkey': pkey,
+            'other_entity': that.other_entity,
+            'values': values,
+            'associator': that.associator,
+            'method': that.delete_method,
+            'on_success': function() {
+                that.refresh();
+                dialog.close();
+            },
+            'on_error': function() {
+                that.refresh();
+                dialog.close();
+            }
+        });
+
+        dialog.init();
+
+        dialog.open(that.container);
+    };
+
     that.refresh = function(){
         that.table.refresh();
     };
diff --git a/install/static/entity.js b/install/static/entity.js
index 9b62ce375f58909b27aba7910ce49bdf16f38443..6e2b501b0989b4549123888bef0fcc69a7b23b0d 100644
--- a/install/static/entity.js
+++ b/install/static/entity.js
@@ -377,6 +377,11 @@ IPA.nested_tabs = function(entity_name){
 
     var siblings = [];
 
+    if (!IPA.tab_set) {
+        siblings.push(entity_name);
+        return siblings;
+    }
+
     for (var top_tab_index = 0;
          top_tab_index < IPA.tab_set.length;
          top_tab_index += 1){
@@ -479,20 +484,7 @@ function ipa_facet_create_action_panel(container) {
             for (var i=1; i<entity.facets.length; i++) {
                 other_facet = entity.facets[i];
                 other_facet_name = other_facet.name;
-
-                if (other_facet.label) {
-                    ul.append(build_link(other_facet,other_facet.label));
-                } else { // For now empty label indicates an association facet
-                    var attribute_members = IPA.metadata[entity_name].attribute_members;
-                    for (var attribute_member in attribute_members) {
-                        var other_entities = attribute_members[attribute_member];
-                        for (var j = 0; j < other_entities.length; j++) {
-                            var other_entity = other_entities[j];
-                            var label = IPA.metadata[other_entity].label;
-                            ul.append(build_link(other_facet,label,other_entity));
-                        }
-                    }
-                }
+                ul.append(build_link(other_facet,other_facet.label));
             }
         }else{
             $('<li/>', {
@@ -507,7 +499,7 @@ function ipa_facet_create_action_panel(container) {
                     return false;
                 }
             }).appendTo(ul);
-         }
+        }
     }
     /*When we land on the search page, disable all facets
           that require a pkey until one is selected*/
diff --git a/install/static/group.js b/install/static/group.js
index 0dfae2fdc8380a86c91a3e6e818b927c0d50da8c..bcac40982d1bddaec55bdb46173df0b65e2bfb68 100644
--- a/install/static/group.js
+++ b/install/static/group.js
@@ -193,6 +193,19 @@ function ipa_group_member_user_facet(spec) {
         that.create_column({name: 'telephonenumber', label: 'Phone'});
         that.create_column({name: 'title', label: 'Job Title'});
 
+        that.create_adder_column({
+            name: 'cn',
+            label: 'Name',
+            width: '100px'
+        });
+
+        that.create_adder_column({
+            name: 'uid',
+            label: 'Login',
+            primary_key: true,
+            width: '100px'
+        });
+
         that.association_facet_init();
     };
 
diff --git a/install/static/hbac.js b/install/static/hbac.js
index 0d6ed7373991a07ad663fc0a20df01f06a4b3389..e2c1266c4fcde2e5f640111b377f831666b98c35 100755
--- a/install/static/hbac.js
+++ b/install/static/hbac.js
@@ -884,7 +884,7 @@ function ipa_hbac_accesstime_widget(spec) {
         for (var i=0; values && i<values.length; i++) {
             var record = {};
             record[that.name] = values[i];
-            that.table.add_row(record);
+            that.table.add_record(record);
         }
     };
 
diff --git a/install/static/hbacsvcgroup.js b/install/static/hbacsvcgroup.js
index f06fe4f9dd7c64c0c2d6782e424d546ff73896cd..9cc1cdea4fba86c36ab99fbcf2f96ceda50b99b1 100755
--- a/install/static/hbacsvcgroup.js
+++ b/install/static/hbacsvcgroup.js
@@ -169,7 +169,8 @@ function ipa_hbacsvcgroup_member_hbacsvc_facet(spec) {
         var column = that.create_column({
             name: 'cn',
             label: 'Service',
-            primary_key: true
+            primary_key: true,
+            width: '150px'
         });
 
         column.setup = function(container, record) {
@@ -193,7 +194,24 @@ function ipa_hbacsvcgroup_member_hbacsvc_facet(spec) {
             }).appendTo(container);
         };
 
-        that.create_column({name: 'description', label: 'Description'});
+        that.create_column({
+            name: 'description',
+            label: 'Description',
+            width: '150px'
+        });
+
+        that.create_adder_column({
+            name: 'cn',
+            label: 'Service',
+            primary_key: true,
+            width: '100px'
+        });
+
+        that.create_adder_column({
+            name: 'description',
+            label: 'Description',
+            width: '100px'
+        });
 
         that.association_facet_init();
     };
diff --git a/install/static/ipa.css b/install/static/ipa.css
index e8faec0068fbc980808a836b7e91c9ea2a725209..7a3f3e89a1700b886bc695d0372e9287528f52fb 100644
--- a/install/static/ipa.css
+++ b/install/static/ipa.css
@@ -327,7 +327,7 @@ span.main-separator{
     margin-left: 2.5em;
     padding-left: 0.5em;
     padding-bottom: 1em;
-    width: 17.5em;
+    width: 16.5em;
 }
 
 
diff --git a/install/static/rule.js b/install/static/rule.js
index 0fc91835782ebb723ce203e5b503e7669fc05b21..b73fb56a7f51ff33354e0ebf82bb4498a2ae6869 100755
--- a/install/static/rule.js
+++ b/install/static/rule.js
@@ -160,7 +160,7 @@ function ipa_rule_association_widget(spec) {
         for (var i=0; values && i<values.length; i++) {
             var record = {};
             record[that.name] = values[i];
-            that.add_row(record);
+            that.add_record(record);
         }
     };
 
diff --git a/install/static/search.js b/install/static/search.js
index e79a534a88615dd37b6a0f3ff412cbd57ea22e0a..f267c701a06f9b637e2f8436d7dcf72a75439683 100644
--- a/install/static/search.js
+++ b/install/static/search.js
@@ -211,7 +211,7 @@ function ipa_search_widget(spec) {
             var result = data.result.result;
             for (var i = 0; i<result.length; i++) {
                 var record = that.get_record(result[i], 0);
-                that.add_row(record);
+                that.add_record(record);
             }
 
             var summary = $('span[name=summary]', that.tfoot);
diff --git a/install/static/service.js b/install/static/service.js
index 39081289f5378445ab69fbf718f4ad7ab29335cf..670737468103eabf25544592635f1852f31e4b7b 100644
--- a/install/static/service.js
+++ b/install/static/service.js
@@ -432,6 +432,19 @@ function ipa_service_managedby_host_facet(spec) {
 
         that.create_column({name: 'description', label: 'Description'});
 
+        that.create_adder_column({
+            name: 'fqdn',
+            label: 'Name',
+            primary_key: true,
+            width: '100px'
+        });
+
+        that.create_adder_column({
+            name: 'description',
+            label: 'Description',
+            width: '100px'
+        });
+
         that.association_facet_init();
     };
 
diff --git a/install/static/sudocmdgroup.js b/install/static/sudocmdgroup.js
index 22762aec0e0dd7ae70e0172da52983649f2331c6..09b2a741c9a7656b50abfedc2bf754a955581db8 100755
--- a/install/static/sudocmdgroup.js
+++ b/install/static/sudocmdgroup.js
@@ -172,7 +172,8 @@ function ipa_sudocmdgroup_member_sudocmd_facet(spec) {
         var column = that.create_column({
             name: 'sudocmd',
             label: 'Command',
-            primary_key: true
+            primary_key: true,
+            width: '150px'
         });
 
         column.setup = function(container, record) {
@@ -196,7 +197,24 @@ function ipa_sudocmdgroup_member_sudocmd_facet(spec) {
             }).appendTo(container);
         };
 
-        that.create_column({name: 'description', label: 'Description'});
+        that.create_column({
+            name: 'description',
+            label: 'Description',
+            width: '150px'
+        });
+
+        that.create_adder_column({
+            name: 'sudocmd',
+            label: 'Command',
+            primary_key: true,
+            width: '100px'
+        });
+
+        that.create_adder_column({
+            name: 'description',
+            label: 'Description',
+            width: '100px'
+        });
 
         that.association_facet_init();
     };
diff --git a/install/static/test/data/hbacsvc_find.json b/install/static/test/data/hbacsvc_find.json
index 1c4b2f5335e84f81433efa5be8eb88299a97b247..09373a338320fb2f23fc85030ec455edded67808 100644
--- a/install/static/test/data/hbacsvc_find.json
+++ b/install/static/test/data/hbacsvc_find.json
@@ -2,7 +2,7 @@
     "error": null,
     "id": 0,
     "result": {
-        "count": 7,
+        "count": 10,
         "result": [
             {
                 "cn": [
@@ -66,6 +66,33 @@
                     "sudo-i"
                 ],
                 "dn": "cn=sudo-i,cn=hbacservices,cn=accounts,dc=dev,dc=example,dc=com"
+            },
+            {
+                "cn": [
+                    "gdm"
+                ],
+                "description": [
+                    "gdm"
+                ],
+                "dn": "cn=gdm,cn=hbacservices,cn=accounts,dc=dev,dc=example,dc=com"
+            },
+            {
+                "cn": [
+                    "gdm-password"
+                ],
+                "description": [
+                    "gdm-password"
+                ],
+                "dn": "cn=gdm-password,cn=hbacservices,cn=accounts,dc=dev,dc=example,dc=com"
+            },
+            {
+                "cn": [
+                    "kdm"
+                ],
+                "description": [
+                    "kdm"
+                ],
+                "dn": "cn=kdm,cn=hbacservices,cn=accounts,dc=dev,dc=example,dc=com"
             }
         ],
         "summary": null,
diff --git a/install/static/widget.js b/install/static/widget.js
index ea6821d12c9f9b8ca6ce74dbc290013686742823..f7b857f6bb92f8dbcadf73c2bba3710b06825564 100755
--- a/install/static/widget.js
+++ b/install/static/widget.js
@@ -32,6 +32,9 @@ function ipa_widget(spec) {
     that.read_only = spec.read_only;
     that._entity_name = spec.entity_name;
 
+    that.width = spec.width;
+    that.height = spec.height;
+
     that.undo = typeof spec.undo == 'undefined' ? true : spec.undo;
 
     that.init = spec.init || init;
@@ -433,6 +436,8 @@ function ipa_column(spec) {
     that.primary_key = spec.primary_key;
     that.setup = spec.setup || setup;
 
+    that.width = spec.width;
+
     function setup(container, record) {
 
         container.empty();
@@ -452,8 +457,7 @@ function ipa_table_widget(spec) {
 
     var that = ipa_widget(spec);
 
-    that.add = spec.add;
-    that.remove = spec.remove;
+    that.scrollable = spec.scrollable;
 
     that.columns = [];
     that.columns_by_name = {};
@@ -498,10 +502,14 @@ function ipa_table_widget(spec) {
 
         var thead = $('<thead/>').appendTo(table);
 
+        if (that.scrollable) {
+            thead.css('display', 'block');
+        }
+
         var tr = $('<tr/>').appendTo(thead);
 
         var th = $('<th/>', {
-            'style': 'width: 25px;'
+            'style': 'width: 22px;'
         }).appendTo(tr);
 
         $('<input/>', {
@@ -511,8 +519,21 @@ function ipa_table_widget(spec) {
 
         for (var i=0; i<that.columns.length; i++) {
             var column = that.columns[i];
+
             th = $('<th/>').appendTo(tr);
 
+            if (that.scrollable && (i == that.columns.length-1)) {
+                if (column.width) {
+                    var width = parseInt(column.width.substring(0, column.width.length-2));
+                    width += 16;
+                    th.css('width', width+'px');
+                }
+            } else {
+                if (column.width) {
+                    th.css('width', column.width);
+                }
+            }
+
             var label = column.label;
 
             $('<span/>', {
@@ -530,9 +551,20 @@ function ipa_table_widget(spec) {
 
         var tbody = $('<tbody/>').appendTo(table);
 
+        if (that.scrollable) {
+            tbody.css('display', 'block');
+            tbody.css('overflow', 'auto');
+        }
+
+        if (that.height) {
+            tbody.css('height', that.height);
+        }
+
         tr = $('<tr/>').appendTo(tbody);
 
-        var td = $('<td/>').appendTo(tr);
+        var td = $('<td/>', {
+            'style': 'width: 22px;'
+        }).appendTo(tr);
 
         $('<input/>', {
             'type': 'checkbox',
@@ -541,10 +573,15 @@ function ipa_table_widget(spec) {
         }).appendTo(td);
 
         for (var i=0; i<that.columns.length; i++) {
+            var column = that.columns[i];
+
             td = $('<td/>').appendTo(tr);
+            if (column.width) {
+                td.css('width', column.width);
+            }
 
             $('<span/>', {
-                'name': that.columns[i].name
+                'name': column.name
             }).appendTo(td);
         }
 
@@ -591,16 +628,20 @@ function ipa_table_widget(spec) {
         that.row.detach();
     };
 
-    that.load = function(result) {
-
+    that.empty = function() {
         that.tbody.empty();
+    };
+
+    that.load = function(result) {
+
+        that.empty();
 
         var values = result[that.name];
         if (!values) return;
 
         for (var i=0; i<values.length; i++) {
             var record = that.get_record(result, i);
-            that.add_row(record);
+            that.add_record(record);
         }
     };
 
@@ -614,7 +655,7 @@ function ipa_table_widget(spec) {
         return values;
     };
 
-    that.get_selected_values = function(container) {
+    that.get_selected_values = function() {
         var values = [];
 
         $('input[name="select"]:checked', that.tbody).each(function() {
@@ -635,7 +676,7 @@ function ipa_table_widget(spec) {
         return record;
     };
 
-    that.add_row = function(record) {
+    that.add_record = function(record) {
 
         var tr = that.row.clone();
         tr.appendTo(that.tbody);
@@ -662,6 +703,23 @@ function ipa_table_widget(spec) {
         }
     };
 
+    that.add_rows = function(rows) {
+        for (var i=0; i<rows.length; i++) {
+            that.tbody.append(rows[i]);
+        }
+    };
+
+    that.remove_selected_rows = function() {
+        var rows = [];
+        that.tbody.children().each(function() {
+            var tr = $(this);
+            if (!$('input[name="select"]', tr).get(0).checked) return;
+            tr.detach();
+            rows.push(tr);
+        });
+        return rows;
+    };
+
     that.refresh = function() {
 
         function on_success(data, text_status, xhr) {
@@ -849,7 +907,7 @@ function ipa_adder_dialog(spec) {
 
     var that = ipa_dialog(spec);
 
-    that.width = spec.width || 600;
+    that.width = spec.width || '600px';
 
     that.columns = [];
     that.columns_by_name = {};
@@ -864,12 +922,42 @@ function ipa_adder_dialog(spec) {
         that.columns_by_name[column.name] = column;
     };
 
+    that.set_columns = function(columns) {
+        that.clear_columns();
+        for (var i=0; i<columns.length; i++) {
+            that.add_column(columns[i]);
+        }
+    };
+
+    that.clear_columns = function() {
+        that.columns = [];
+        that.columns_by_name = {};
+    };
+
     that.create_column = function(spec) {
         var column = ipa_column(spec);
         that.add_column(column);
         return column;
     };
 
+    that.init = function() {
+        that.available_table = ipa_table_widget({
+            name: 'available',
+            scrollable: true,
+            height: 150
+        });
+
+        that.available_table.set_columns(that.columns);
+
+        that.selected_table = ipa_table_widget({
+            name: 'selected',
+            scrollable: true,
+            height: 150
+        });
+
+        that.selected_table.set_columns(that.columns);
+    };
+
     that.create = function() {
 
         // do not call that.dialog_create();
@@ -888,23 +976,35 @@ function ipa_adder_dialog(spec) {
         var results_panel = $('<div/>').appendTo(that.container);
         results_panel.css('border', '2px solid rgb(0, 0, 0)');
         results_panel.css('position', 'relative');
+        results_panel.css('width', '100%');
         results_panel.css('height', '200px');
 
-        var available_panel = $('<div/>').appendTo(results_panel);
-        available_panel.css('float', 'left');
+        var available_title = $('<div/>', {
+            html: 'Available',
+            style: 'float: left; width: 250px;'
+        }).appendTo(results_panel);
 
-        $('<div/>', {
-            text: 'Available'
-        }).appendTo(available_panel);
+        var buttons_title = $('<div/>', {
+            html: '&nbsp;',
+            style: 'float: left; width: 50px;'
+        }).appendTo(results_panel);
 
-        that.available_list = $('<select/>', {
-            width: '150px',
-            size: '10',
-            multiple: 'true'
-        }).appendTo(available_panel);
+        var selected_title = $('<div/>', {
+            html: 'Prospective',
+            style: 'float: left; width: 250px;'
+        }).appendTo(results_panel);
 
-        var buttons_panel = $('<div/>').appendTo(results_panel);
-        buttons_panel.css('float', 'left');
+        var available_panel = $('<div/>', {
+            name: 'available',
+            style: 'clear:both; float: left; width: 250px; height: 150px;'
+        }).appendTo(results_panel);
+
+        that.available_table.create(available_panel);
+
+        var buttons_panel = $('<div/>', {
+            name: 'buttons',
+            style: 'float: left; width: 50px; height: 150px; text-align: center;'
+        }).appendTo(results_panel);
 
         var p = $('<p/>').appendTo(buttons_panel);
         that.remove_button = $('<input />', {
@@ -918,36 +1018,32 @@ function ipa_adder_dialog(spec) {
             value: '>>'
         }).appendTo(p);
 
-        var selected_panel = $('<div/>').appendTo(results_panel);
-        selected_panel.css('float', 'left');
+        var selected_panel = $('<div/>', {
+            name: 'selected',
+            style: 'float: left; width: 250px; height: 150px;'
+        }).appendTo(results_panel);
 
-        $('<div/>', {
-            text: 'Prospective'
-        }).appendTo(selected_panel);
-
-        that.selected_list = $('<select/>', {
-            width: '150px',
-            size: '10',
-            multiple: 'true'
-        }).appendTo(selected_panel);
+        that.selected_table.create(selected_panel);
     };
 
     that.setup = function() {
 
         // do not call that.dialog_setup();
 
+        var available_panel = $('div[name=available]', that.container);
+        that.available_table.setup(available_panel);
+
+        var selected_panel = $('div[name=selected]', that.container);
+        that.selected_table.setup(selected_panel);
+
         that.add_button.click(function(){
-            var values = $(':selected', that.available_list).detach();
-            values.each(function(i, selected){
-                that.selected_list.append(selected);
-            });
+            var rows = that.available_table.remove_selected_rows();
+            that.selected_table.add_rows(rows);
         });
 
         that.remove_button.click(function(){
-            var values = $(':selected', that.selected_list).detach();
-            values.each(function(i, selected){
-                that.available_list.append(selected);
-            });
+            var rows = that.selected_table.remove_selected_rows();
+            that.available_table.add_rows(rows);
         });
 
         that.find_button.click(function(){
@@ -969,44 +1065,26 @@ function ipa_adder_dialog(spec) {
     };
 
     that.clear_available_values = function() {
-        that.available_list.html('');
+        that.available_table.empty();
     };
 
     that.clear_selected_values = function() {
-        that.selected_list.html('');
+        that.selected_table.empty();
     };
 
     that.add_available_value = function(record) {
-
-        var name = that.columns[0].name;
-        var value = record[name];
-        value = value ? value.toString() : '';
-
-        $('<option></option>',{
-            'value': value,
-            'html': value
-        }).appendTo(that.available_list);
-    };
-
-    that.add_selected_value = function(value) {
-        $('<option></option>',{
-            'value': value,
-            'html': value
-        }).appendTo(that.available_list);
+        that.available_table.add_record(record);
     };
 
     that.get_selected_values = function() {
-        var values = [];
-        that.selected_list.children().each(function (i, selected) {
-            values.push(selected.value);
-        });
-        return values;
+        return that.selected_table.save();
     };
 
     that.close = function() {
         that.container.dialog('close');
     };
 
+    that.adder_dialog_init = that.init;
     that.adder_dialog_create = that.create;
     that.adder_dialog_setup = that.setup;
 
-- 
1.6.6.1

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

Reply via email to