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.
This commit is contained in:
Endi S. Dewata 2010-12-01 14:51:39 -06:00 committed by Adam Young
parent 620c085ebf
commit c0eb2b60c8
12 changed files with 383 additions and 189 deletions

View File

@ -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,26 +438,43 @@ 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.create = function(container) {
that.init = function() {
that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
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;
//TODO I18N
var header_message = that.other_entity + '(s) enrolled in ' +
that.entity_name + ' ' + that.pkey;
$('<div/>', {
'id': that.entity_name+'-'+that.other_entity,
html: $('<h2/>',{ html: header_message })
}).appendTo(container);
that.table = ipa_association_table_widget({
'id': that.entity_name+'-'+that.other_entity,
'name': that.name,
@ -540,6 +488,25 @@ function ipa_association_facet(spec) {
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) || '';
//TODO I18N
var header_message = that.other_entity + '(s) enrolled in ' +
that.entity_name + ' ' + that.pkey;
$('<div/>', {
'id': that.entity_name+'-'+that.other_entity,
html: $('<h2/>',{ html: header_message })
}).appendTo(container);
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();
};

View File

@ -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*/

View File

@ -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();
};

View File

@ -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);
}
};

View File

@ -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();
};

View File

@ -327,7 +327,7 @@ span.main-separator{
margin-left: 2.5em;
padding-left: 0.5em;
padding-bottom: 1em;
width: 17.5em;
width: 16.5em;
}

View File

@ -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);
}
};

View File

@ -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);

View File

@ -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();
};

View File

@ -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();
};

View File

@ -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,

View File

@ -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.empty = function() {
that.tbody.empty();
};
that.load = function(result) {
that.tbody.empty();
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;