summaryrefslogtreecommitdiffstats
path: root/install
diff options
context:
space:
mode:
authorEndi S. Dewata <edewata@redhat.com>2010-11-02 20:16:55 -0500
committerAdam Young <ayoung@redhat.com>2010-11-04 14:22:32 -0400
commitd99ebc0f3798c84e612c79c43eb85c31b20ab1ce (patch)
treef2a758dfc9028d32f00236340b409469c73848a4 /install
parent05a16f50d7fe8c01408ec445e6b5ad26ff65d9d5 (diff)
downloadfreeipa-d99ebc0f3798c84e612c79c43eb85c31b20ab1ce.tar.gz
freeipa-d99ebc0f3798c84e612c79c43eb85c31b20ab1ce.tar.xz
freeipa-d99ebc0f3798c84e612c79c43eb85c31b20ab1ce.zip
HBAC Details Page
The UI framework has been extended to include a collection of widgets: - ipa_widget: base class - ipa_text_widget: text field - ipa_radio_widget: radio button - ipa_textarea_widget: textarea - ipa_button_widget: button - ipa_column_widget: column for table - ipa_table_widget: table These widgets can be used to create input controls. They can also be extended to create custom controls. The framework has also been enhanced to support custom layouts. This can be used to change the look of the application without changing the code. Initially this is only available in details section. Layout consists of a collection of HTML templates. Each template is a complete and valid HTML file representing a portion of a page. The template will be loaded and initialized by the code, then filled with the data from the server. The layouts are located in install/static/layouts/<name> folder. By default, if no templates are used, the fields in the details page are rendered vertically using dd/dt/dd tags. For pages that require different layout, a custom UI needs to be developed. There are two ways to do that: - write a custom widget to generate the UI dynamically - create an HTML template and write the initialization code For components that are quite complex or used frequently, it's might be better to use the first method. For simple pages that are used only in one location or need to support customization, the second method might be preferable. Other benefits of templates: - cleaner code and UI separation - more flexibility in customization - new pages can be developed quickly and require less coding - multiple templates can be used with the same initialization code - easier to maintain The HBAC details page has been implemented using both methods. By default it will use custom widgets to generate the page. To use a custom layout, add the following parameter to the URL, then reload the page: &layout=<name> Currently the only available layout is 'default' which produces the same look as the custom widgets. The HBAC details page is usable, but it still needs additional work. The access time is not working yet. There is no undo button, hint, or validation yet. The table in the association facet has also been changed to use ipa_association_widget which is derived from ipa_table_widget. The Makefile has been updated to include the layouts. The unit tests have been updated as well.
Diffstat (limited to 'install')
-rw-r--r--install/configure.ac2
-rw-r--r--install/static/Makefile.am2
-rw-r--r--install/static/add.js24
-rw-r--r--install/static/associate.js717
-rwxr-xr-xinstall/static/certificate.js26
-rw-r--r--install/static/details.js366
-rw-r--r--install/static/entity.js65
-rwxr-xr-xinstall/static/hbac.js664
-rw-r--r--install/static/host.js7
-rw-r--r--install/static/index.xhtml1
-rw-r--r--install/static/ipa.css19
-rw-r--r--install/static/ipa.js11
-rw-r--r--install/static/layouts/Makefile.am22
-rw-r--r--install/static/layouts/default/Makefile.am25
-rwxr-xr-xinstall/static/layouts/default/hbac-details-accesstime.html46
-rwxr-xr-xinstall/static/layouts/default/hbac-details-general.html45
-rwxr-xr-xinstall/static/layouts/default/hbac-details-host.html75
-rwxr-xr-xinstall/static/layouts/default/hbac-details-service.html75
-rwxr-xr-xinstall/static/layouts/default/hbac-details-sourcehost.html75
-rwxr-xr-xinstall/static/layouts/default/hbac-details-user.html75
-rw-r--r--install/static/navigation.js6
-rw-r--r--install/static/policy.js25
-rw-r--r--install/static/search.js66
-rw-r--r--install/static/service.js23
-rw-r--r--install/static/test/all_tests.html1
-rw-r--r--install/static/test/association_tests.js46
-rw-r--r--install/static/test/details_tests.html1
-rw-r--r--install/static/test/details_tests.js187
-rw-r--r--install/static/test/entity_tests.html1
-rw-r--r--install/static/test/entity_tests.js2
-rw-r--r--install/static/test/navigation_tests.html2
-rw-r--r--install/static/user.js18
-rwxr-xr-xinstall/static/widget.js473
33 files changed, 2436 insertions, 757 deletions
diff --git a/install/configure.ac b/install/configure.ac
index 3d0c1db02..5cdfb791e 100644
--- a/install/configure.ac
+++ b/install/configure.ac
@@ -73,6 +73,8 @@ AC_CONFIG_FILES([
migration/Makefile
share/Makefile
static/Makefile
+ static/layouts/Makefile
+ static/layouts/default/Makefile
tools/Makefile
tools/man/Makefile
updates/Makefile
diff --git a/install/static/Makefile.am b/install/static/Makefile.am
index 7097a1f6a..787cc4185 100644
--- a/install/static/Makefile.am
+++ b/install/static/Makefile.am
@@ -3,6 +3,7 @@ AUTOMAKE_OPTIONS = 1.7
NULL =
SUBDIRS = \
+ layouts \
$(NULL)
appdir = $(IPA_DATA_DIR)/static
@@ -32,6 +33,7 @@ app_DATA = \
details.js \
entity.js \
webui.js \
+ widget.js \
user.js \
ipalogo.png \
gray-fade-line.png \
diff --git a/install/static/add.js b/install/static/add.js
index b5f9c16d4..fbf9031b9 100644
--- a/install/static/add.js
+++ b/install/static/add.js
@@ -31,10 +31,19 @@ function ipa_add_field(spec) {
var that = {};
that.name = spec.name;
that.label = spec.label;
+ that._entity_name = spec.entity_name;
that.init = spec.init;
that.setup = spec.setup;
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+ });
+
return that;
}
@@ -45,7 +54,7 @@ function ipa_add_dialog(spec) {
var that = {};
that.name = spec.name;
that.title = spec.title;
- that.entity_name = spec.entity_name;
+ that._entity_name = spec.entity_name;
that.init = spec.init;
@@ -54,6 +63,18 @@ function ipa_add_dialog(spec) {
var dialog = $('<div/>');
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+
+ for (var i=0; i<that.fields.length; i++) {
+ that.fields[i].entity_name = entity_name;
+ }
+ });
+
that.get_fields = function() {
return that.fields;
};
@@ -85,6 +106,7 @@ function ipa_add_dialog(spec) {
} else {
dialog.append('<label>' + field.label + '</label>');
dialog.append('<input type="text" name="' + field.name + '" />');
+ dialog.append('<br/>');
}
}
diff --git a/install/static/associate.js b/install/static/associate.js
index 2050e468e..088d4079a 100644
--- a/install/static/associate.js
+++ b/install/static/associate.js
@@ -22,227 +22,196 @@
/* CURRENTLY ALSO REQUIRES search.js, because it reuses it's code to create
* the AssociationList elements; IT NEEDS IT'S OWN CODE! */
+function ipa_associator(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.entity_name = spec.entity_name;
+ that.pkey = spec.pkey;
+
+ that.other_entity = spec.other_entity;
+ that.values = spec.values;
+
+ that.method = spec.method;
+
+ that.on_success = spec.on_success;
+ that.on_error = spec.on_error;
+
+ that.execute = function() {
+ };
+
+ return that;
+}
+
/**
*This associator is built for the case where each association requires a separate rpc
*/
-function serial_associate(form, manyObjPkeys, on_success)
-{
- var associator = this;
- this.form = form;
- this.manyObjPkeys = manyObjPkeys;
- this.on_success = on_success;
-
- this.associate_next = function(){
- var form = this.form;
- //TODO assert pre-conditions
- var manyObjPkey = manyObjPkeys.shift();
- if (manyObjPkey){
- var options = {};
- options[form.oneObj] = form.pkey;
- var args = [manyObjPkey];
-
- ipa_cmd( form.method,args, options ,
- function(data, text_status, xhr) {
- if (data.error){
- alert('error adding member: '+data.error.message);
- }else{
- associator.associate_next();
- }
- },
- function(xhr, text_status, error_thrown) {
- alert('associateFailure');
- },
- form.manyObj );
- }else{
- associator.on_success();
- }
- }
- this.associate_next();
-}
+function serial_associator(spec) {
+ spec = spec || {};
-function serial_delete(delete_method, one_entity, one_entity_pkey, many_entity,
- many_entity_pkeys, on_success){
- var that = {};
- that.one_entity = one_entity;
- that.on_success = on_success;
- that.many_entity_pkeys = many_entity_pkeys;
- that.delete_next = function(){
- var many_entity_pkey = this.many_entity_pkeys.shift();
- if (many_entity_pkey){
- var options = {};
- options[one_entity] = one_entity_pkey;
- var args = [many_entity_pkey];
- ipa_cmd( delete_method,args, options ,
- function(data, text_status, xhr) {
- if (data.error){
- alert("error deleting member: "
- +data.error.message);
- }else{
- that.delete_next();
- }
- },
- function(xhr, text_status, error_thrown) {
- alert("associateFailure");
- },
- many_entity );
- }else{
- this.on_success();
+ var that = ipa_associator(spec);
+
+ that.execute = function() {
+
+ if (!that.values || !that.values.length) {
+ that.on_success();
+ return;
}
- }
- that.delete_next();
-}
+ var value = that.values.shift();
+ if (!value) {
+ that.on_success();
+ return;
+ }
-function bulk_delete(delete_method, one_entity, one_entity_pkey, many_entity,
- many_entity_pkeys, on_success){
- if (many_entity_pkeys.length){
+ var args = [value];
var options = {};
- options[one_entity] = one_entity_pkey;
- var option = many_entity_pkeys.shift();
- while(many_entity_pkeys.length > 0) {
- option += ',' + many_entity_pkeys.shift();
- }
+ options[that.entity_name] = that.pkey;
+
+ ipa_cmd(
+ that.method,
+ args,
+ options,
+ that.execute,
+ that.on_error,
+ that.other_entity
+ );
+ };
- var options = {
- 'all':true
- };
- options[many_entity] = option;
- var args = [one_entity_pkey];
- ipa_cmd( delete_method,args, options ,
- function(data, text_status, xhr) {
- if (data.error){
- alert("error deleting member: "
- +data.error.message);
- }else{
- on_success();
- }
- },
- function(xhr, text_status, error_thrown) {
- alert("associateFailure");
- },
- one_entity );
- }else{
- on_success();
- }
+ return that;
}
-
/**
*This associator is for the common case where all the asociations can be sent
in a single rpc
*/
-function bulk_associate(form, manyObjPkeys, on_success)
-{
- var associator = this;
- this.form = form;
- this.manyObjPkeys = manyObjPkeys;
- this.on_success = on_success;
-
- var form = this.form;
- var option = manyObjPkeys.shift();
- while(manyObjPkeys.length > 0) {
- option += ',' + manyObjPkeys.shift();
- }
- var options = {
- 'all':true
+function bulk_associator(spec) {
+
+ spec = spec || {};
+
+ var that = ipa_associator(spec);
+
+ that.execute = function() {
+
+ if (!that.values || !that.values.length) {
+ that.on_success();
+ return;
+ }
+
+ var value = that.values.shift();
+ if (!value) {
+ that.on_success();
+ return;
+ }
+
+ while (that.values.length > 0) {
+ value += ',' + that.values.shift();
+ }
+
+ var args = [that.pkey];
+ var options = { 'all': true };
+ options[that.other_entity] = value;
+
+ ipa_cmd(
+ that.method,
+ args,
+ options,
+ that.on_success,
+ that.on_error,
+ that.entity_name
+ );
};
- options[form.manyObj] = option;
- var args = [form.pkey];
- ipa_cmd( form.method,args, options ,
- function(data, text_status, xhr) {
- if (data.error){
- alert('error adding member: '+data.error.message);
- }else{
- associator.on_success();
- }
- },
- function(xhr, text_status, error_thrown) {
- alert('associateFailure');
- },
- form.oneObj );
+
+ return that;
}
/**
* Create a form for a one to many association.
*
*/
-function AssociationForm(oneObj, pkey, manyObj, on_success, associator, method)
-{
- var form = this;
+function ipa_adder_dialog(spec) {
- this.oneObj = oneObj;
- this.pkey = pkey;
- this.manyObj = manyObj;
- this.on_success = on_success;
+ spec = spec || {};
- this.dialog = $('<div></div>');
+ var that = {};
- //An optional parameter to determine what ipa method to call to create
- //the association
- if (method)
- this.method = method;
- else
- this.method = 'add_member';
+ that.name = spec.name;
+ that.title = spec.title;
+ that.entity_name = spec.entity_name;
- this.associator = associator;
+ that.pkey = spec.pkey;
+ that.other_entity = spec.other_entity;
+ that.setup = spec.setup || ipa_adder_dialog_setup;
+ that.execute = spec.execute || execute;
+ that.on_success = spec.on_success;
+ that.on_error = spec.on_error;
+ that.associator = spec.associator;
+ that.method = spec.method || 'add_member';
- this.setup = function() {
- var label = IPA.metadata[form.manyObj].label;
+ that.dialog = $('<div/>', {
+ 'title': that.title
+ });
- form.dialog.attr('title', 'Enroll '+form.oneObj+' '+form.pkey+' in '+label);
+ that.open = function() {
- association_form_create(form.dialog);
+ that.setup();
- var availableList = $('#availableList', form.dialog);
+ var availableList = $('#availableList', that.dialog);
availableList.html('');
- var enrollments = $('#enrollments', form.dialog);
+ var enrollments = $('#enrollments', that.dialog);
enrollments.html('');
- $('#addToList', form.dialog).click(function(){
- $('#availableList :selected', form.dialog).each(function(i, selected){
+ $('#addToList', that.dialog).click(function(){
+ $('#availableList :selected', that.dialog).each(function(i, selected){
enrollments.append(selected);
});
- $('#availableList :selected', form.dialog).remove();
+ $('#availableList :selected', that.dialog).remove();
});
- $('#removeFromList', form.dialog).click(function(){
- $('#enrollments :selected', form.dialog).each(function(i, selected){
+ $('#removeFromList', that.dialog).click(function(){
+ $('#enrollments :selected', that.dialog).each(function(i, selected){
availableList.append(selected);
});
- $('#enrollments :selected', form.dialog).remove();
+ $('#enrollments :selected', that.dialog).remove();
});
- $('#find', form.dialog).click(function(){
- form.search();
+ $('#find', that.dialog).click(function(){
+ that.search();
});
- form.dialog.dialog({
+ that.dialog.dialog({
modal: true,
width: 600,
buttons: {
- 'Enroll': function(evt) {
- form.associate(form.on_success);
+ 'Enroll': function() {
+ var values = [];
+ $('#enrollments', that.dialog).children().each(function (i, selected) {
+ values.push(selected.value);
+ });
+ that.execute(values);
},
- 'Cancel': form.close
+ 'Cancel': that.close
}
});
};
- this.close = function() {
- form.dialog.dialog('close');
+ that.close = function() {
+ that.dialog.dialog('close');
};
- this.search = function() {
+ that.search = function() {
function search_on_win(data, text_status, xhr) {
var results = data.result;
- var list = $('#availableList', form.dialog);
+ var list = $('#availableList', that.dialog);
list.html('');
- var searchColumn = IPA.metadata[form.manyObj].primary_key;
+ var searchColumn = IPA.metadata[that.other_entity].primary_key;
for (var i =0; i != results.count; i++){
var result = results.result[i];
@@ -257,246 +226,298 @@ function AssociationForm(oneObj, pkey, manyObj, on_success, associator, method)
alert('associationSearchFailure');
}
- var queryFilter = $('#associateFilter', form.dialog).val();
- ipa_cmd('find', [queryFilter], {}, search_on_win, null, form.manyObj);
+ var queryFilter = $('#associateFilter', that.dialog).val();
+ ipa_cmd('find', [queryFilter], {}, search_on_win, null, that.other_entity);
};
- this.associate = function (on_success) {
- var manyObjPkeys = [];
- $('#enrollments', form.dialog).children().each(function (i, selected) {
- manyObjPkeys.push(selected.value);
+ that.get_values = function() {
+ var values = [];
+ $('#enrollments', that.dialog).children().each(function (i, selected) {
+ values.push(selected.value);
});
- this.associator(form, manyObjPkeys, on_success);
+ return values;
};
-}
-function ipa_association_config(spec) {
- spec = spec || {};
+ function execute(values) {
- var that = {};
+ var associator = that.associator({
+ 'entity_name': that.entity_name,
+ 'pkey': that.pkey,
+ 'other_entity': that.other_entity,
+ 'values': that.get_values(),
+ 'method': that.method,
+ 'on_success': that.on_success,
+ 'on_error': that.on_error
+ });
- that.name = spec.name;
- that.associator = spec.associator;
- that.method = spec.method;
+ associator.execute();
+ }
return that;
}
-function ipa_association_facet(spec) {
+function ipa_deleter_dialog(spec) {
spec = spec || {};
- var that = ipa_facet(spec);
+ var that = {};
- that.configs = [];
- that.configs_by_name = {};
+ that.name = spec.name;
+ that.title = spec.title || IPA.messages.button.deletes;
+ that.entity_name = spec.entity_name;
- that.other_entity = null;
+ that.pkey = spec.pkey;
+ that.other_entity = spec.other_entity;
+
+ that.setup = spec.setup || ipa_deleter_dialog_setup;
+ that.execute = spec.execute || execute;
+ that.on_success = spec.on_success;
+ that.on_error = spec.on_error;
+
+ that.associator = spec.associator;
+ that.method = spec.method || 'remove_member';
+
+ that.values = spec.values || [];
- that.get_configs = function() {
- return that.configs;
+ that.dialog = $('<div/>', {
+ 'title': that.title,
+ 'class': 'search-dialog-delete'
+ });
+
+ that.add_value = function(value) {
+ that.values.push(value);
};
- that.get_config = function(name) {
- return that.configs_by_name[name];
+ that.set_values = function(values) {
+ that.values = that.values.concat(values);
};
- that.add_config = function(config) {
- that.configs.push(config);
- that.configs_by_name[config.name] = config;
+ that.get_values = function() {
+ return that.values;
};
- that.create_config = function(spec) {
- var config = ipa_association_config(spec);
- that.add_config(config);
- return config;
+ that.open = function() {
+
+ that.setup();
+
+ that.dialog.dialog({
+ modal: true,
+ width: 400,
+ buttons: {
+ 'Delete': that.execute,
+ 'Cancel': that.close
+ }
+ });
};
- that.is_dirty = function() {
- var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
- var other_entity = $.bbq.getState(that.entity_name + '-enroll', true) || '';
- return pkey != that.pkey || other_entity != that.other_entity;
+ function execute() {
+
+ var associator = that.associator({
+ 'entity_name': that.entity_name,
+ 'pkey': that.pkey,
+ 'other_entity': that.other_entity,
+ 'values': that.values,
+ 'method': that.method,
+ 'on_success': that.on_success,
+ 'on_error': that.on_error
+ });
+
+ associator.execute();
+ }
+
+ that.close = function() {
+ that.dialog.dialog('close');
};
- that.setup = function(container, unspecified) {
+ return that;
+}
- that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
- that.other_entity = $.bbq.getState(that.entity_name + '-enroll', true) || '';
+function ipa_association_config(spec) {
+ spec = spec || {};
- that.member_attrribute = ipa_get_member_attribute(that.entity_name, that.other_entity);
- that.columns = [
- {
- 'title': IPA.metadata[that.other_entity].label,
- 'column': that.member_attrribute + '_' + that.other_entity
- }
- ];
+ var that = {};
- var config = that.get_config(that.other_entity);
+ that.name = spec.name;
+ that.associator = spec.associator;
+ that.add_method = spec.add_method;
+ that.delete_method = spec.delete_method;
- if ( config && config.associator === 'serial' ){
- that.associator = serial_associate;
- that.deleter = serial_delete;
- }else{
- that.associator = bulk_associate;
- that.deleter = bulk_delete;
- }
+ return that;
+}
- that.method = config ? config.method : null;
+function ipa_association_widget(spec) {
- that.setup_views(container);
+ spec = spec || {};
- //TODO I18N
- var header_message = that.other_entity + '(s) enrolled in ' +
- that.entity_name + ' ' + that.pkey;
- container.append($('<h2/>',{html: header_message }) );
- association_list_create(that.entity_name, container);
- container.find('.search-filter').css('display', 'none');
- container.find('.search-buttons').html('');
+ spec.add = spec.add || add;
+ spec.remove = spec.remove || remove;
+
+ var that = ipa_table_widget(spec);
+
+ that.other_entity = spec.other_entity;
+
+ that.super_create = that.super('create');
+ that.super_setup = that.super('setup');
+
+ that.create = function(container) {
+
+ that.member_attribute = ipa_get_member_attribute(that.entity_name, that.other_entity);
- var ctrls = container.find('.search-buttons');
+ that.create_column({
+ 'name': that.member_attribute + '_' + that.other_entity,
+ 'label': IPA.metadata[that.other_entity].label,
+ 'primary_key': true
+ });
+
+ that.super_create(container);
+
+ var div = $('#'+that.id, container);
+ var buttons = $('span[name=buttons]', div);
- ipa_make_button( 'ui-icon-plus',IPA.messages.button.enroll).
- click(function() {
- that.show_enrollment_dialog(container);
- }).appendTo(ctrls);
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'remove',
+ 'value': IPA.messages.button.delete
+ }).appendTo(buttons);
- ipa_make_button('ui-icon-trash',IPA.messages.button.delete).
- click(function(){
- that.delete_on_click(container);
- }).appendTo(ctrls);
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'add',
+ 'value': IPA.messages.button.enroll
+ }).appendTo(buttons);
+ }
+
+ that.setup = function(container) {
+ that.super_setup(container);
+ var entity = IPA.get_entity(that.entity_name);
+ var association = entity.get_association(that.other_entity);
- var header = container.find('.search-table thead:last').find("tr");;
- for (var i =0 ; i != that.columns.length ;i++){
- $('<th></th>',{
- html: that.columns[i].title
- }).appendTo(header);
+ if (association && association.associator == 'serial') {
+ that.associator = serial_associator;
+ } else {
+ that.associator = bulk_associator;
}
- that.refresh(container);
+
+ that.add_method = association ? association.add_method : null;
+ that.delete_method = association ? association.delete_method : null;
};
- that.delete_on_click = function(container) {
- var delete_list = [];
- var delete_dialog = $('<div></div>', {
- title: IPA.messages.button.delete,
- 'class': 'search-dialog-delete'
- });
+ function add(container) {
- function delete_on_click() {
- that.deleter('remove_member', that.entity_name,
- that.pkey, that.other_entity, delete_list,
- function(){ that.refresh(container)});
- delete_dialog.dialog('close');
- }
- function delete_on_win() {
- delete_dialog.dialog('close');
- }
- function cancel_on_click() {
- delete_dialog.dialog('close');
- }
- var confirm_list = $('<ul/>');
- var delete_list = [];
- container.find('.search-selector').each(function () {
- if (this.checked){
- delete_list.push(this.title);
- confirm_list.append($('<li/>',{text: this.title}));
+ 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_adder_dialog({
+ 'name': '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(container);
+ dialog.close();
+ },
+ 'on_error': function() {
+ that.refresh(container);
+ dialog.close();
}
});
- if (delete_list.length == 0){
+
+ dialog.open();
+ }
+
+ function remove(container) {
+
+ var values = that.get_selected_values();
+
+ if (!values.length) {
+ alert('Select '+that.label+' to be removed.');
return;
}
- delete_dialog.append(confirm_list);
- delete_dialog.append(
- $('<p/>',
- {text:IPA.messages.search.delete_confirm}));
-
- delete_dialog.dialog({
- modal: true,
- buttons: {
- 'Delete': delete_on_click,
- 'Cancel': cancel_on_click
+ 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_deleter_dialog({
+ 'name': '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(container);
+ dialog.close();
+ },
+ 'on_error': function() {
+ that.refresh(container);
+ dialog.close();
}
});
+
+ dialog.open();
}
- that.refresh = function(container) {
+ return that;
+}
- function refresh_on_success(data, text_status, xhr) {
- var tbody = container.find('.search-table tbody');
- tbody.empty();
- var associationList = data.result.result[that.columns[0].column];
- //TODO, this is masking an error where the wrong
- //direction association is presented upon page reload.
- //if the associationList is unset, it is because
- //form.associationColumns[0] doesn't exist in the results
- if (!associationList) return;
+function ipa_association_facet(spec) {
+ spec = spec || {};
- for (var j = 0; j < associationList.length; j++){
- var association = associationList[j];
- var row = $('<tr/>').appendTo(tbody);
- search_generate_checkbox_td(row, association);
+ var that = ipa_facet(spec);
+ that.other_entity = null;
- for (var k = 0; k < that.columns.length ;k++){
- var column = that.columns[k].column;
- $('<td></td>',{
- html:data.result.result[column][j],
- }).appendTo(row);
- }
- }
+ that.is_dirty = function() {
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var other_entity = $.bbq.getState(that.entity_name + '-enroll', true) || '';
+ return pkey != that.pkey || other_entity != that.other_entity;
+ };
- tbody.find('.search-a-pkey').click(function () {
- var jobj = $(this);
- var state = {};
- state[that.other_entity + '-facet'] = 'details';
- state[that.other_entity + '-pkey'] = $(this).text();
- //Before this will work, we need to set the tab one level up
- //for example:
- //state['identity'] = 0;
- //but we have no way of getting the index.
-
- $.bbq.pushState(state);
- return (false);
- });
- }
+ that.setup = function(container, unspecified) {
- function refresh_on_error(xhr, text_status, error_thrown) {
- var search_results = $('.search-results', container).empty();
- search_results.append('<p>Error: '+error_thrown.name+'</p>');
- search_results.append('<p>'+error_thrown.title+'</p>');
- search_results.append('<p>'+error_thrown.message+'</p>');
- }
+ that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ that.other_entity = $.bbq.getState(that.entity_name + '-enroll', true) || '';
- ipa_cmd('show', [that.pkey], {}, refresh_on_success, refresh_on_error, that.entity_name);
- };
+ that.setup_views(container);
- that.show_enrollment_dialog = function(container) {
+ //TODO I18N
+ var header_message = that.other_entity + '(s) enrolled in ' +
+ that.entity_name + ' ' + that.pkey;
+ container.append( $('<h2/>',{ html: header_message }) );
+ $('<div/>', {
+ 'id': that.entity_name+'-'+that.other_entity
+ }).appendTo(container);
+ var table = ipa_association_widget({
+ 'id': that.entity_name+'-'+that.other_entity,
+ 'name': that.other_entity, 'label': IPA.metadata[that.other_entity].label,
+ 'entity_name': that.entity_name, 'other_entity': that.other_entity
+ });
- var enrollment_dialog = new AssociationForm(
- that.entity_name,
- that.pkey,
- that.other_entity,
- function() {
- that.refresh(container);
- enrollment_dialog.close();
- },
- that.associator,
- that.method
- );
- enrollment_dialog.setup();
+ table.create(container);
+ table.setup(container);
+ table.refresh(container);
};
return that;
}
-function association_form_create(jobj)
-{
+function ipa_adder_dialog_setup() {
+
+ var that = this;
+
var div = $('<div id="associations"></div>');
var form = $('<form></form>');
@@ -561,27 +582,8 @@ function association_form_create(jobj)
}));
form_div.append(sub_div);
form.append(form_div);
- form.append($('<hr />'));
- form.append($('<div></div>', {
- text: 'Message Area'
- }));
- form.append($('<hr />'));
- var form_div = $('<div></div>');
- var span = $('<span></span>');
- span.css('float', 'left');
- span.append($('<p></p>', {
- text: '*Enter Group Names and Press Groups'
- }));
- span.append($('<p></p>', {
- text: '*More stuff'
- }));
- span.append($('<p></p>', {
- text: '*More stuff'
- }));
- form_div.append(span);
- form.append(form_div);
div.append(form);
- jobj.append(div);
+ that.dialog.append(div);
}
function association_list_create(obj_name, jobj)
@@ -589,3 +591,20 @@ function association_list_create(obj_name, jobj)
search_create(obj_name, [], jobj);
}
+function ipa_deleter_dialog_setup() {
+
+ var that = this;
+
+ var ul = $('<ul/>');
+ ul.appendTo(that.dialog);
+
+ for (var i=0; i<that.values.length; i++) {
+ $('<li/>',{
+ 'text': that.values[i]
+ }).appendTo(ul);
+ }
+
+ $('<p/>', {
+ 'text': IPA.messages.search.delete_confirm
+ }).appendTo(that.dialog);
+} \ No newline at end of file
diff --git a/install/static/certificate.js b/install/static/certificate.js
index e1297a834..affc58aa4 100755
--- a/install/static/certificate.js
+++ b/install/static/certificate.js
@@ -421,10 +421,9 @@ function certificate_status_panel(spec) {
td.append('Valid Certificate Present:');
td = $('<td/>').appendTo(tr);
- $('<input/>', {
+ ipa_button({
'id': 'get_button',
- 'type': 'button',
- 'value': 'Get',
+ 'label': 'Get',
'click': function() {
ipa_cmd(that.entity_type+'_show', [pkey], {},
function(data, text_status, xhr) {
@@ -434,10 +433,9 @@ function certificate_status_panel(spec) {
}
}).appendTo(td);
- $('<input/>', {
+ ipa_button({
'id': 'revoke_button',
- 'type': 'button',
- 'value': 'Revoke',
+ 'label': 'Revoke',
'click': function() {
ipa_cmd(that.entity_type+'_show', [pkey], {},
function(data, text_status, xhr) {
@@ -447,10 +445,9 @@ function certificate_status_panel(spec) {
}
}).appendTo(td);
- $('<input/>', {
+ ipa_button({
'id': 'view_button',
- 'type': 'button',
- 'value': 'View',
+ 'label': 'View',
'click': function() {
ipa_cmd(that.entity_type+'_show', [pkey], {},
function(data, text_status, xhr) {
@@ -476,10 +473,9 @@ function certificate_status_panel(spec) {
}));
td.append(' ');
- $('<input/>', {
+ ipa_button({
'id': 'restore_button',
- 'type': 'button',
- 'value': 'Restore',
+ 'label': 'Restore',
'click': function() {
ipa_cmd(that.entity_type+'_show', [pkey], {},
function(data, text_status, xhr) {
@@ -500,9 +496,9 @@ function certificate_status_panel(spec) {
td.append('No Valid Certificate:');
td = $('<td/>').appendTo(tr);
- $('<input/>', {
- 'type': 'button',
- 'value': 'New Certificate',
+ ipa_button({
+ 'id': 'create_button',
+ 'label': 'New Certificate',
'click': function() {
request_certificate(that.result);
}
diff --git a/install/static/details.js b/install/static/details.js
index e4cbec77e..e69a5dace 100644
--- a/install/static/details.js
+++ b/install/static/details.js
@@ -30,39 +30,44 @@ function ipa_details_field(spec) {
spec = spec || {};
- var that = {};
- that.name = spec.name;
- that.label = spec.label;
+ spec.create = spec.create || create;
+ spec.setup = spec.setup || setup;
+ spec.load = spec.load || load;
+ spec.save = spec.save || save;
+
+ var that = ipa_widget(spec);
+
+ function create(container) {
+ }
- that.setup = spec.setup || setup;
- that.load = spec.load || load;
- that.save = spec.save || save;
+ function setup(container) {
- function setup(container, dl, section) {
+ var dl = $('dl', container);
- var obj_name = container.attr('title');
- var title = this.name;
+ var title = that.name;
var label = '';
- var param_info = ipa_get_param_info(obj_name, this.name);
+ var param_info = ipa_get_param_info(that.entity_name, that.name);
if (param_info)
label = param_info['label'];
if (!label)
- label = this.label;
+ label = that.label;
$('<dt></dt>', {
- id: this.name,
+ id: that.name,
title: title,
html: label + ':'
}).appendTo(dl);
}
- function load(container, dt, entry_attrs) {
+ function load(container, result) {
- var obj_name = container.attr('id');
var multivalue = false;
var hint_span = null;
var dd;
- var param_info = ipa_get_param_info(obj_name, this.name);
+ var dt = $('dt[title='+that.name+']', container);
+ if (!dt.length) return;
+
+ var param_info = ipa_get_param_info(that.entity_name, that.name);
if (param_info) {
if (param_info['multivalue'] || param_info['class'] == 'List')
multivalue = true;
@@ -74,35 +79,35 @@ function ipa_details_field(spec) {
}
}
- var value = entry_attrs[this.name];
+ var value = result[that.name];
if (value) {
dd = ipa_create_first_dd(
- this.name, ipa_create_input(obj_name, this.name, value[0],hint_span)
+ that.name, ipa_create_input(that.entity_name, that.name, value[0],hint_span)
);
dt.after(dd);
var last_dd = dd;
for (var i = 1; i < value.length; ++i) {
dd = ipa_create_other_dd(
- this.name, ipa_create_input(obj_name, this.name, value[i],hint_span)
+ that.name, ipa_create_input(that.entity_name, that.name, value[i],hint_span)
);
last_dd.after(dd);
last_dd = dd;
}
if (multivalue) {
dd = ipa_create_other_dd(
- this.name, _ipa_a_add_template.replace('A', this.name)
+ that.name, _ipa_a_add_template.replace('A', that.name)
);
last_dd.after(dd);
}
} else {
if (multivalue) {
dd = ipa_create_first_dd(
- this.name, _ipa_a_add_template.replace('A', this.name) /*.append(hint_span)*/
+ that.name, _ipa_a_add_template.replace('A', that.name) /*.append(hint_span)*/
);
dt.after(dd);
} else {
dd = ipa_create_first_dd(
- this.name, ipa_create_input(obj_name, this.name, '') /*.append(hint_span)*/
+ that.name, ipa_create_input(that.entity_name, that.name, '') /*.append(hint_span)*/
);
dt.after(dd);
}
@@ -139,10 +144,35 @@ function ipa_details_section(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 = {};
+ that.super = function(name) {
+ var method = that[name];
+ return function () {
+ return method.apply(that, arguments);
+ };
+ };
+
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+
+ for (var i=0; i<that.fields.length; i++) {
+ that.fields[i].entity_name = entity_name;
+ }
+ });
+
that.get_fields = function() {
return that.fields;
};
@@ -152,6 +182,7 @@ function ipa_details_section(spec){
};
that.add_field = function(field) {
+ field.entity_name = that.entity_name;
that.fields.push(field);
that.fields_by_name[field.name] = field;
};
@@ -162,6 +193,30 @@ function ipa_details_section(spec){
return field;
};
+ that.create_text = function(spec) {
+ var field = ipa_text_widget(spec);
+ that.add_field(field);
+ return field;
+ };
+
+ that.create_radio = function(spec) {
+ var field = ipa_radio_widget(spec);
+ that.add_field(field);
+ return field;
+ };
+
+ that.create_textarea = function(spec) {
+ var field = ipa_textarea_widget(spec);
+ that.add_field(field);
+ return field;
+ };
+
+ that.create_button = function(spec) {
+ var field = ipa_button_widget(spec);
+ that.add_field(field);
+ return field;
+ };
+
// Deprecated: Used for backward compatibility only.
function input(spec){
that.create_field(spec);
@@ -184,12 +239,26 @@ function ipa_details_facet(spec) {
var that = ipa_facet(spec);
- that.init = spec.init;
- that.setup = spec.setup || setup;
+ that.init = spec.init || init;
+ that.is_dirty = spec.is_dirty || ipa_details_is_dirty;
+ that.setup = spec.setup || ipa_details_setup;
+ that.create = spec.create || ipa_details_create;
that.sections = [];
that.sections_by_name = {};
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+
+ for (var i=0; i<that.sections.length; i++) {
+ that.sections[i].entity_name = entity_name;
+ }
+ });
+
that.get_sections = function() {
return that.sections;
};
@@ -199,70 +268,87 @@ function ipa_details_facet(spec) {
};
that.add_section = function(section) {
+ section.entity_name = that.entity_name;
that.sections.push(section);
that.sections_by_name[section.name] = section;
};
that.create_section = function(spec) {
- var section = ipa_stanza(spec);
+ var section = ipa_details_section(spec);
that.add_section(section);
return section;
};
- that.is_dirty = function() {
- var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
- return pkey != that.pkey;
- };
-
- function setup(container, unspecified) {
+ function init() {
+ }
- that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ return that;
+}
- that.setup_views(container);
- ipa_details_create(container, that.sections);
+function ipa_button(spec) {
- container.find('.details-reset').click(function() {
- ipa_details_reset(container);
- return false;
- });
+ spec = spec || {};
- container.find('.details-update').click(function() {
- var pkey_name = IPA.metadata[that.entity_name].primary_key;
- ipa_details_update(container, ipa_details_cache[that.entity_name][pkey_name][0]);
- return false;
- });
+ var button = $('<a/>', {
+ 'id': spec.id,
+ 'html': spec.label,
+ 'class': 'ui-state-default ui-corner-all input_link'
+ });
- if (that.pkey||unspecified){
- ipa_details_load(container, that.pkey, null, null);
- }
- }
+ if (spec.click) button.click(spec.click);
+ if (spec.class) button.addClass(spec.class);
+ if (spec.icon) button.append('<span class="ui-icon '+spec.icon+'" ></span> ');
- if (that.init) that.init();
+ return button;
+}
- return that;
+function ipa_details_is_dirty() {
+ var pkey = $.bbq.getState(this.entity_name + '-pkey', true) || '';
+ return pkey != this.pkey;
}
-function ipa_make_button(which,text,details_class){
+function ipa_details_setup(container, unspecified) {
- var button_class= details_class +
- " ui-state-default ui-corner-all input_link ";
- return $('<a ></a>',{
- "class": button_class
- }).
- append('<span class="ui-icon ' + which +'" ></span> ').
- append(text);
+ var facet = this;
+
+ facet.setup_views(container);
+
+ facet.pkey = $.bbq.getState(facet.entity_name + '-pkey', true) || '';
+ if (!facet.pkey && !unspecified) return;
+
+ function on_success(data, text_status, xhr) {
+ var result = data.result.result;
+
+ ipa_details_cache[facet.entity_name] = $.extend(true, {}, result);
+ facet.create(container, result);
+ }
+
+ function on_failure(xhr, text_status, error_thrown) {
+ var details = $('.details', container).empty();
+ details.append('<p>Error: '+error_thrown.name+'</p>');
+ details.append('<p>'+error_thrown.title+'</p>');
+ details.append('<p>'+error_thrown.message+'</p>');
+ }
+
+ var params = [];
+ if (facet.pkey) params.push(facet.pkey);
+
+ ipa_cmd(
+ 'show', params, {all: true}, on_success, on_failure, facet.entity_name
+ );
}
-function ipa_details_create(container, sections)
+function ipa_details_create(container, result)
{
+ var facet = this;
+
if (!container) {
alert('ERROR: ipa_details_create: Missing container argument!');
return;
}
- var obj_name = container.attr('id');
- container.attr('title', obj_name);
- container.addClass('details-container');
+ var entity_name = container.attr('id');
+ container.attr('title', entity_name);
var details = $('<div/>', {
'class': 'details'
@@ -272,81 +358,97 @@ function ipa_details_create(container, sections)
'class': 'details-buttons'
}).appendTo(details);
- buttons.append(ipa_make_button('ui-icon-refresh','Reset','details-reset'));
- buttons.append(ipa_make_button('ui-icon-check','Update','details-update'));
-
- details.append('<hr />');
-
- for (var i = 0; i < sections.length; ++i) {
- var section = sections[i];
- ipa_details_section_setup(container, details, section);
- }
+ buttons.append(ipa_button({
+ 'label': 'Reset',
+ 'icon': 'ui-icon-refresh',
+ 'class': 'details-reset',
+ 'click': function() {
+ ipa_details_reset(container);
+ return false;
+ }
+ }));
-}
+ var pkey_name = IPA.metadata[facet.entity_name].primary_key;
+ buttons.append(ipa_button({
+ 'label': 'Update',
+ 'icon': 'ui-icon-check',
+ 'class': 'details-update',
+ 'click': function() {
+ ipa_details_update(container, ipa_details_cache[facet.entity_name][pkey_name][0]);
+ return false;
+ }
+ }));
-function ipa_details_section_setup(container, details, section)
-{
- var id = section.name;
- var name = section.label;
- var fields = section.fields;
+ details.append('<br/>');
+ details.append('<hr/>');
- if (!fields)
- return;
+ for (var i = 0; i < facet.sections.length; ++i) {
+ var section = facet.sections[i];
- details.append($("<h2/>",{
- click: function(){_h2_on_click(this)},
- html:"&#8722; "+name
- }));
+ details.append($('<h2/>',{
+ click: function(){_h2_on_click(this)},
+ html:"&#8722; "+section.label
+ }));
- var dl = $('<dl></dl>',{
- id:id,
- "class":"entryattrs"
- }).appendTo(details);
+ var div = $('<div/>', {
+ 'id': facet.entity_name+'-'+facet.name+'-'+section.name,
+ 'class': 'details-section'
+ }).appendTo(details);
- for (var i = 0; i < fields.length; ++i) {
- var field = fields[i];
+ section.setup(div, result);
- field.setup(container, dl, section);
+ details.append('<hr/>');
}
-
- details.append('<hr/>');
}
-function ipa_details_load(container, pkey, on_win, on_fail)
-{
- var obj_name = container.attr('id');
-
- function load_on_win(data, text_status, xhr) {
- if (on_win)
- on_win(data, text_status, xhr);
- if (data.error)
- return;
+function ipa_details_section_setup(container, result) {
+ var section = this;
+ var fields = section.get_fields();
- var result = data.result.result;
- ipa_details_cache[obj_name] = $.extend(true, {}, result);
- ipa_details_display(container, result);
+ if (section.template) {
+ var template = IPA.get_template(section.template);
+ container.load(template, function(data, text_status, xhr) {
+ for (var i = 0; i < fields.length; ++i) {
+ var field = fields[i];
+ field.create(container);
+ field.setup(container);
+ field.load(container, result);
+ }
+ });
+ return;
}
- function load_on_fail(xhr, text_status, error_thrown) {
- if (on_fail)
- on_fail(xhr, text_status, error_thrown);
+ section.create(container);
- var details = $('.details', container).empty();
- details.append('<p>Error: '+error_thrown.name+'</p>');
- details.append('<p>'+error_thrown.title+'</p>');
- details.append('<p>'+error_thrown.message+'</p>');
+ for (var i = 0; i < fields.length; ++i) {
+ var field = fields[i];
+ field.create(container);
+ field.setup(container);
+ field.load(container, result);
}
+}
- var params = [pkey];
- if (!pkey){
- params = [];
+function ipa_details_section_create(container, result) {
+ var section = this;
+
+ var dl = $('<dl/>', {
+ 'id': section.name,
+ 'class': 'entryattrs'
+ }).appendTo(container);
+}
+
+function ipa_details_section_load(container, result) {
+ var section = this;
+ var fields = section.get_fields();
+
+ for (var j=0; j<fields.length; j++) {
+ var field = fields[j];
+ field.load(container, result);
}
- ipa_cmd(
- 'show', params, {all: true}, load_on_win, load_on_fail, obj_name
- );
}
+
function ipa_details_update(container, pkey, on_win, on_fail)
{
var obj_name = container.attr('id');
@@ -378,13 +480,14 @@ function ipa_details_update(container, pkey, on_win, on_fail)
var sections = facet.get_sections();
for (var i=0; i<sections.length; i++) {
var section = sections[i];
- var fields = section.fields;
- if (!fields) continue;
+ var fields = section.get_fields();
+
+ var div = $('#'+facet.entity_name+'-'+facet.name+'-'+section.name, container);
for (var j=0; j<fields.length; j++) {
var field = fields[j];
- values = field.save(container);
+ values = field.save(div);
var param_info = ipa_get_param_info(obj_name, field.name);
if (param_info) {
@@ -434,29 +537,24 @@ var _ipa_span_hint_template = '<span class="attrhint">Hint: D</span>';
* </dl>
*
* arguments:
- * entry_attrs - 'result' field as returned by ipa *-show commnads
+ * result - 'result' field as returned by ipa *-show commnads
* (basically an associative array with attr:value pairs) */
-function ipa_details_display(container, entry_attrs)
+function ipa_details_display(container, result)
{
- var obj_name = container.attr('id');
+ var entity_name = container.attr('id');
/* remove all <dd> tags i.e. all attribute values */
$('dd', container).remove();
/* go through all <dt> tags and pair them with newly created <dd>s */
- var facet = ipa_entity_get_details_facet(obj_name);
+ var facet = ipa_entity_get_details_facet(entity_name);
var sections = facet.get_sections();
for (var i=0; i<sections.length; i++) {
var section = sections[i];
- var fields = section.fields;
- if (!fields) continue;
- for (var j=0; j<fields.length; j++) {
- var field = fields[j];
- var dt = $('dt[title='+field.name+']', container);
- if (!dt.length) continue;
- field.load(container, dt, entry_attrs);
- }
+ var div = $('#'+facet.entity_name+'-'+facet.name+'-'+section.name, container);
+
+ section.load(div, result);
}
}
@@ -501,10 +599,10 @@ var _ipa_param_type_2_handler_map = {
* arguments:
* attr - LDAP attribute name
* value - the attributes value */
-function ipa_create_input(obj_name, attr, value,hint)
+function ipa_create_input(entity_name, attr, value,hint)
{
var input = $("<label>",{html:value.toString()});
- var param_info = ipa_get_param_info(obj_name, attr);
+ var param_info = ipa_get_param_info(entity_name, attr);
if (!param_info) {
/* no information about the param is available, default to text input */
input = _ipa_create_text_input(attr, value, null);
@@ -606,7 +704,7 @@ function _ipa_create_text_input(attr, value, param_info)
style:"display:none",
click: function(){
var key = this.previousElementSibling.name;
- var entity_divs = $(this).parents('.details-container');
+ var entity_divs = $(this).parents('.entity-container');
var entry_attrs = ipa_details_cache[entity_divs[0].id];
index = calculate_dd_index($(this));
@@ -649,7 +747,7 @@ function _ipa_add_on_click(obj)
var jobj = $(obj);
var attr = jobj.attr('title');
var par = jobj.parent();
- var obj_name = jobj.closest('.details-container').attr('title');
+ var obj_name = jobj.closest('.entity-container').attr('title');
var param_info = ipa_get_param_info(obj_name, '');
var input = _ipa_create_text_input(attr, '', param_info);
diff --git a/install/static/entity.js b/install/static/entity.js
index f26f219b7..24a49fc76 100644
--- a/install/static/entity.js
+++ b/install/static/entity.js
@@ -28,11 +28,19 @@ function ipa_facet(spec) {
var that = {};
that.name = spec.name;
that.label = spec.label;
- that.entity_name = spec.entity_name;
+ that._entity_name = spec.entity_name;
that.init = spec.init;
that.setup = spec.setup;
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+ });
+
that.setup_views = ipa_facet_setup_views;
return that;
@@ -55,6 +63,9 @@ function ipa_entity(spec) {
this.facet_name = null;
+ that.associations = [];
+ that.associations_by_name = {};
+
that.get_add_dialog = function() {
return that.add_dialog;
};
@@ -74,31 +85,49 @@ function ipa_entity(spec) {
};
that.add_facet = function(facet) {
+ facet.entity_name = that.name;
that.facets.push(facet);
that.facets_by_name[facet.name] = facet;
};
that.create_search_facet = function(spec) {
- spec.entity_name = that.name;
var facet = ipa_search_facet(spec);
that.add_facet(facet);
return facet;
};
that.create_details_facet = function(spec) {
- spec.entity_name = that.name;
var facet = ipa_details_facet(spec);
that.add_facet(facet);
+ facet.init();
return facet;
};
that.create_association_facet = function(spec) {
- spec.entity_name = that.name;
var facet = ipa_association_facet(spec);
that.add_facet(facet);
return facet;
};
+ that.get_associations = function() {
+ return that.associations;
+ };
+
+ that.get_association = function(name) {
+ return that.associations_by_name[name];
+ };
+
+ that.add_association = function(config) {
+ that.associations.push(config);
+ that.associations_by_name[config.name] = config;
+ };
+
+ that.create_association = function(spec) {
+ var config = ipa_association_config(spec);
+ that.add_association(config);
+ return config;
+ };
+
return that;
}
@@ -213,14 +242,17 @@ function ipa_entity_get_association_facet(entity_name) {
function ipa_entity_set_association_definition(entity_name, data) {
- var facet = ipa_entity_get_association_facet(entity_name);
+ var entity = ipa_get_entity(entity_name);
+
+ ipa_entity_get_association_facet(entity_name);
for (var other_entity in data) {
var config = data[other_entity];
- facet.create_config({
+ entity.create_association({
'name': other_entity,
'associator': config.associator,
- 'method': config.method
+ 'add_method': config.add_method,
+ 'delete_method': config.delete_method
});
}
}
@@ -231,7 +263,6 @@ function ipa_entity_set_facet_definition(entity_name, list) {
for (var i=0; i<list.length; i++) {
var facet = list[i];
- facet.entity_name = entity_name;
entity.add_facet(facet);
}
}
@@ -244,8 +275,6 @@ function ipa_entity_setup(container, unspecified) {
var entity = this;
- container.empty();
-
var facet_name = $.bbq.getState(entity.name + '-facet', true) || unspecified || 'search';
var facet = entity.get_facet(facet_name);
@@ -262,6 +291,8 @@ function ipa_entity_setup(container, unspecified) {
IPA.entity_name = entity.name;
}
+ container.empty();
+
if (facet.setup) {
facet.setup(container, unspecified);
}
@@ -271,7 +302,7 @@ function ipa_facet_setup_views(container) {
var facet = this;
- var ul = $('<ul/>', {'class': 'entity-views'});
+ var ul = $('<ul/>', {'class': 'entity-views'}).appendTo(container);
var entity = IPA.get_entity(facet.entity_name);
var facets = entity.get_facets();
@@ -289,7 +320,9 @@ function ipa_facet_setup_views(container) {
title: other_facet.name,
text: label,
click: function(entity_name, facet_name) {
- return function() { IPA.show_page(entity_name, facet_name); }
+ return function() {
+ IPA.show_page(entity_name, facet_name);
+ };
}(facet.entity_name, facet_name)
}));
@@ -308,20 +341,20 @@ function ipa_facet_setup_views(container) {
title: other_entity,
text: label,
click: function(entity_name, facet_name, other_entity) {
- return function() { IPA.show_page(entity_name, facet_name, other_entity); }
+ return function() {
+ IPA.show_page(entity_name, facet_name, other_entity);
+ };
}(facet.entity_name, facet_name, other_entity)
}));
}
}
}
}
-
- container.append(ul);
}
function ipa_entity_quick_links(tr, attr, value, entry_attrs) {
- var obj_name = tr.closest('.search-container').attr('title');
+ var obj_name = tr.closest('.entity-container').attr('title');
var pkey = IPA.metadata[obj_name].primary_key;
var pkey_value = entry_attrs[pkey][0];
diff --git a/install/static/hbac.js b/install/static/hbac.js
index 94b05fbd4..528fdec92 100755
--- a/install/static/hbac.js
+++ b/install/static/hbac.js
@@ -27,6 +27,7 @@ function ipa_hbac() {
});
that.init = function() {
+
that.create_add_dialog({
'name': 'add',
'title': 'Add New Rule',
@@ -43,12 +44,7 @@ function ipa_hbac() {
that.create_details_facet({
'name': 'details',
'label': 'Details',
- 'init': ipa_hbac_details_init,
- 'setup': ipa_hbac_details_setup
- });
-
- that.create_association_facet({
- 'name': 'associate'
+ 'init': ipa_hbac_details_init
});
};
@@ -61,6 +57,7 @@ IPA.add_entity(ipa_hbac());
function ipa_hbac_add_init() {
this.create_field({name:'cn', label:'Rule Name'});
+ this.create_field({name:'accessruletype', label:'Rule type (allow/deny)'});
}
function ipa_hbac_search_init() {
@@ -81,51 +78,51 @@ function ipa_hbac_search_init() {
function ipa_hbac_search_setup(container) {
- var facet = this;
+ var that = this;
- facet.filter = $.bbq.getState(facet.entity_name + '-filter', true) || '';
+ that.filter = $.bbq.getState(that.entity_name + '-filter', true) || '';
+/*
+ // Not yet implemented
- var toolbar = $('<span/>').appendTo(container);
+ var left_buttons = $('<span/>', {
+ 'style': 'float: left;'
+ }).appendTo(container);
- $('<input/>', {
- 'type': 'button',
- 'value': 'Troubleshoot Rules',
- 'click': function() {
- }
- }).appendTo(toolbar);
+ left_buttons.append(ipa_button({
+ 'label': 'Troubleshoot Rules'
+ }));
- $('<input/>', {
- 'type': 'button',
- 'value': 'Cull Disabled Rules',
- 'click': function() {
- }
- }).appendTo(toolbar);
+ left_buttons.append(ipa_button({
+ 'label': 'Cull Disabled Rules'
+ }));
- $('<input/>', {
- 'type': 'button',
- 'value': 'Login Services',
- 'click': function() {
- }
- }).appendTo(toolbar);
+ var right_buttons = $('<span/>', {
+ 'style': 'float: right;'
+ }).appendTo(container);
- $('<input/>', {
- 'type': 'button',
- 'value': 'Login Svc Groups',
- 'click': function() {
- }
- }).appendTo(toolbar);
+ right_buttons.append(ipa_button({
+ 'label': 'Login Services'
+ }));
+
+ right_buttons.append(ipa_button({
+ 'label': 'Login Svc Groups'
+ }));
- search_create(facet.entity_name, facet.columns, container);
+ container.append('<br/><br/>');
+*/
+ search_create(that.entity_name, that.columns, container);
- ipa_make_button('ui-icon-plus', IPA.messages.button.add).
- click(function() {
- var entity = IPA.get_entity(facet.entity_name);
+ ipa_button({
+ 'label': IPA.messages.button.add,
+ 'icon': 'ui-icon-plus',
+ 'click': function() {
+ var entity = IPA.get_entity(that.entity_name);
entity.add_dialog.open();
return false;
- }).
- appendTo($('.search-controls', container));
+ }
+ }).appendTo($('.search-controls', container));
- search_load(container, facet.filter);
+ search_load(container, that.filter);
}
function ipa_hbac_quick_links(tr, attr, value, entry_attrs) {
@@ -133,7 +130,7 @@ function ipa_hbac_quick_links(tr, attr, value, entry_attrs) {
var column = this;
var facet = column.facet;
- var pkey = IPA.metadata[facet.entity_name].primary_key;
+ var pkey = IPA.metadata[column.entity_name].primary_key;
var pkey_value = entry_attrs[pkey][0];
var td = $('<td/>').appendTo(tr);
@@ -144,8 +141,8 @@ function ipa_hbac_quick_links(tr, attr, value, entry_attrs) {
'text': 'Details',
'click': function() {
var state = {};
- state[facet.entity_name+'-facet'] = 'details';
- state[facet.entity_name+'-pkey'] = pkey_value;
+ state[column.entity_name+'-facet'] = 'details';
+ state[column.entity_name+'-pkey'] = pkey_value;
nav_push_state(state);
return false;
}
@@ -159,8 +156,8 @@ function ipa_hbac_quick_links(tr, attr, value, entry_attrs) {
'text': 'Test Rule',
'click': function() {
var state = {};
- state[facet.entity_name+'-facet'] = 'test-rule';
- state[facet.entity_name+'-pkey'] = pkey_value;
+ state[column.entity_name+'-facet'] = 'test-rule';
+ state[column.entity_name+'-pkey'] = pkey_value;
nav_push_state(state);
return false;
}
@@ -169,46 +166,565 @@ function ipa_hbac_quick_links(tr, attr, value, entry_attrs) {
function ipa_hbac_details_init() {
- var section = this.create_section({name:'general', label:'General'});
- section.create_field({name:'cn', label:'Name'});
- section.create_field({name:'accessruletype', label:'Rule Type'});
- section.create_field({name:'description', label:'Description'});
- section.create_field({name:'ipaenabledflag', label:'Enabled'});
+ var that = this;
+ var section;
- section = this.create_section({name:'user', label:'Who'});
- section.create_field({name:'usercategory', label:'User Category'});
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'general',
+ 'label': 'General',
+ 'template': 'hbac-details-general.html #contents'
+ });
- section = this.create_section({name:'host', label:'Accessing'});
- section.create_field({name:'hostcategory', label:'Host Category'});
+ } else {
+ section = ipa_hbac_details_general_section({
+ 'name': 'general',
+ 'label': 'General'
+ });
+ that.add_section(section);
+ }
+
+ section.create_text({ 'name': 'cn', 'label': 'Name' });
+ section.create_radio({ 'name': 'accessruletype', 'label': 'Rule Type' });
+ section.create_textarea({ 'name': 'description', 'label': 'Description' });
+ section.create_radio({ 'name': 'ipaenabledflag', 'label': 'Enabled' });
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'user',
+ 'label': 'Who',
+ 'template': 'hbac-details-user.html #contents'
+ });
- section = this.create_section({name:'service', label:'Via Service'});
- section.create_field({name:'servicecategory', label:'Service Category'});
+ } else {
+ section = ipa_hbac_details_tables_section({
+ 'name': 'user',
+ 'label': 'Who',
+ 'text': 'Rule applies when access is requested by:',
+ 'field_name': 'usercategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Anyone' },
+ { 'value': '', 'label': 'Specified Users and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'memberuser_user' },
+ { 'field_name': 'memberuser_group' }
+ ]
+ });
+ that.add_section(section);
+ }
+
+ section.create_radio({ name: 'usercategory', label: 'User category' });
+ section.add_field(ipa_hbac_association_widget({
+ 'id': that.entity_name+'-memberuser_user',
+ 'name': 'memberuser_user', 'label': 'Users',
+ 'other_entity': 'user', 'add_method': 'add_user', 'delete_method': 'remove_user'
+ }));
+ section.add_field(ipa_hbac_association_widget({
+ 'id': that.entity_name+'-memberuser_group',
+ 'name': 'memberuser_group', 'label': 'Groups',
+ 'other_entity': 'group', 'add_method': 'add_user', 'delete_method': 'remove_user'
+ }));
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'host',
+ 'label': 'Accessing',
+ 'template': 'hbac-details-host.html #contents'
+ });
- section = this.create_section({name:'sourcehost', label:'From'});
- section.create_field({name:'sourcehostcategory', label:'Source Host Category'});
+ } else {
+ section = ipa_hbac_details_tables_section({
+ 'name': 'host',
+ 'label': 'Accessing',
+ 'text': 'Rule applies when access is requested to:',
+ 'field_name': 'hostcategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Any Host' },
+ { 'value': '', 'label': 'Specified Hosts and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'memberhost_host' },
+ { 'field_name': 'memberhost_hostgroup' }
+ ],
+ 'columns': [
+ ]
+ });
+ that.add_section(section);
+ }
+
+ section.create_radio({ 'name': 'hostcategory', 'label': 'Host category' });
+ section.add_field(ipa_hbac_association_widget({
+ 'id': that.entity_name+'-memberhost_host',
+ 'name': 'memberhost_host', 'label': 'Hosts',
+ 'other_entity': 'host', 'add_method': 'add_host', 'delete_method': 'remove_host'
+ }));
+ section.add_field(ipa_hbac_association_widget({
+ 'id': that.entity_name+'-memberhost_hostgroup',
+ 'name': 'memberhost_hostgroup', 'label': 'Host Groups',
+ 'other_entity': 'hostgroup', 'add_method': 'add_host', 'delete_method': 'remove_host'
+ }));
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'service',
+ 'label': 'Via Service',
+ 'template': 'hbac-details-service.html #contents'
+ });
+
+ } else {
+ section = ipa_hbac_details_tables_section({
+ 'name': 'service',
+ 'label': 'Via Service',
+ 'text': 'Rule applies when access is requested via:',
+ 'field_name': 'servicecategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Any Service' },
+ { 'value': '', 'label': 'Specified Services and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'memberservice_hbacsvc' },
+ { 'field_name': 'memberservice_hbacsvcgroup' }
+ ]
+ });
+ that.add_section(section);
+ }
+
+ section.create_radio({ 'name': 'servicecategory', 'label': 'Service category' });
+ section.add_field(ipa_hbac_association_widget({
+ 'id': that.entity_name+'-memberservice_hbacsvc',
+ 'name': 'memberservice_hbacsvc', 'label': 'Services',
+ 'other_entity': 'hbacsvc', 'add_method': 'add_service', 'delete_method': 'remove_service'
+ }));
+ section.add_field(ipa_hbac_association_widget({
+ 'id': that.entity_name+'-memberservice_hbacsvcgroup',
+ 'name': 'memberservice_hbacsvcgroup', 'label': 'Service Groups',
+ 'other_entity': 'hbacsvcgroup', 'add_method': 'add_service', 'delete_method': 'remove_service'
+ }));
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'sourcehost',
+ 'label': 'From',
+ 'template': 'hbac-details-sourcehost.html #contents'
+ });
+
+ } else {
+ section = ipa_hbac_details_tables_section({
+ 'name': 'sourcehost',
+ 'label': 'From',
+ 'text': 'Rule applies when access is being initiated from:',
+ 'field_name': 'sourcehostcategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Any Host' },
+ { 'value': '', 'label': 'Specified Hosts and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'sourcehost_host' },
+ { 'field_name': 'sourcehost_hostgroup' }
+ ]
+ });
+ that.add_section(section);
+ }
+
+ section.create_radio({ 'name': 'sourcehostcategory', 'label': 'Source host category' });
+ section.add_field(ipa_hbac_association_widget({
+ 'id': that.entity_name+'-sourcehost_host',
+ 'name': 'sourcehost_host', 'label': 'Host',
+ 'other_entity': 'host', 'add_method': 'add_sourcehost', 'delete_method': 'remove_sourcehost'
+ }));
+ section.add_field(ipa_hbac_association_widget({
+ 'id': that.entity_name+'-sourcehost_hostgroup',
+ 'name': 'sourcehost_hostgroup', 'label': 'Host Groups',
+ 'other_entity': 'hostgroup', 'add_method': 'add_sourcehost', 'delete_method': 'remove_sourcehost'
+ }));
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'accesstime',
+ 'label': 'When',
+ 'template': 'hbac-details-accesstime.html #contents'
+ });
+
+ } else {
+ section = ipa_hbac_details_tables_section({
+ 'name': 'accesstime',
+ 'label': 'When',
+ 'text': 'Rule applies when access is being requested at:',
+ 'field_name': 'sourcehostcategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Any Time' },
+ { 'value': '', 'label': 'Specified Times' }
+ ],
+ 'tables': [
+ { 'field_name': 'accesstime' }
+ ]
+ });
+ that.add_section(section);
+ }
+
+ section.add_field(ipa_hbac_accesstime_widget({
+ 'id': that.entity_name+'-accesstime',
+ 'name': 'accesstime', 'label': 'Access Time'
+ }));
}
-function ipa_hbac_details_setup(container, unspecified) {
+function ipa_hbac_details_general_section(spec){
- var facet = this;
+ spec = spec || {};
- var pkey = $.bbq.getState(facet.entity_name + '-pkey', true);
- var pkey_name = IPA.metadata[facet.entity_name].primary_key;
+ var that = ipa_details_section(spec);
- facet.setup_views(container);
+ that.create = function(container) {
- var sections = facet.get_sections();
- ipa_details_create(container, sections);
+ var table = $('<table/>', {
+ 'style': 'width: 100%;'
+ }).appendTo(container);
- container.find('.details-reset').click(function() {
- ipa_details_reset(container);
- return false;
- });
+ var tr = $('<tr/>', {
+ }).appendTo(table);
- container.find('.details-update').click(function() {
- ipa_details_update(container, ipa_details_cache[facet.entity_name][pkey_name][0]);
- return false;
- });
+ var td = $('<td/>', {
+ 'style': 'width: 100px; text-align: right;',
+ 'html': 'Name:'
+ }).appendTo(tr);
+
+ td = $('<td/>').appendTo(tr);
+
+ $('<input/>', {
+ 'type': 'text',
+ 'name': 'cn',
+ 'size': 30
+ }).appendTo(td);
+
+ td = $('<td/>', {
+ 'style': 'text-align: right;'
+ }).appendTo(tr);
+
+ td.append('Rule type:');
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'accessruletype',
+ 'value': 'allow'
+ }).appendTo(td);
+
+ td.append('Allow');
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'accessruletype',
+ 'value': 'deny'
+ }).appendTo(td);
+
+ td.append('Deny');
+
+ tr = $('<tr/>', {
+ }).appendTo(table);
+
+ td = $('<td/>', {
+ 'style': 'text-align: right; vertical-align: top;',
+ 'html': 'Description:'
+ }).appendTo(tr);
+
+ td = $('<td/>', {
+ 'colspan': 2
+ }).appendTo(tr);
+
+ $('<textarea/>', {
+ 'name': 'description',
+ 'rows': 5,
+ 'style': 'width: 100%'
+ }).appendTo(td);
+
+ tr = $('<tr/>', {
+ }).appendTo(table);
+
+ td = $('<td/>', {
+ 'style': 'text-align: right; vertical-align: top;',
+ 'html': 'Rule status:'
+ }).appendTo(tr);
+
+ td = $('<td/>', {
+ 'colspan': 2
+ }).appendTo(tr);
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipaenabledflag',
+ 'value': 'TRUE'
+ }).appendTo(td);
+
+ td.append('Active');
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipaenabledflag',
+ 'value': 'FALSE'
+ }).appendTo(td);
+
+ td.append('Inactive');
+ };
+
+ return that;
+}
+
+function ipa_hbac_details_tables_section(spec){
+
+ spec = spec || {};
+
+ spec.create = create;
+
+ var that = ipa_details_section(spec);
+
+ that.text = spec.text;
+ that.field_name = spec.field_name;
+ that.options = spec.options;
+ that.tables = spec.tables;
+ that.columns = spec.columns;
+
+ that.super_setup = that.super('setup');
+
+ function create(container) {
+
+ if (that.template) return;
+
+ container.append(that.text);
+
+ for (var i=0; i<that.options.length; i++) {
+ var option = that.options[i];
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': that.field_name,
+ 'value': option.value
+ }).appendTo(container);
+
+ container.append(option.label);
+ }
+
+ container.append('<br/>');
- ipa_details_load(container, pkey, null, null);
+ for (var i=0; i<that.tables.length; i++) {
+ var table = that.tables[i];
+
+ $('<div/>', {
+ 'id': that.entity_name+'-'+table.field_name
+ }).appendTo(container);
+ }
+ }
+
+ return that;
+}
+
+/**
+ * This widget adds & deletes the rows of the table in the UI, but does not
+ * execute IPA command to apply the changes on the server.
+ */
+function ipa_hbac_association_widget(spec) {
+
+ spec = spec || {};
+
+ spec.add = spec.add || add;
+ spec.remove = spec.remove || remove;
+ spec.save = spec.save || save;
+
+ var that = ipa_table_widget(spec);
+
+ that.other_entity = spec.other_entity;
+
+ that.add_method = spec.add_method;
+ that.delete_method = spec.delete_method;
+
+ that.super_create = that.super('create');
+ that.super_setup = that.super('setup');
+
+ that.create = function(container) {
+
+ // create a column when none defined
+ if (!that.columns.length) {
+ that.create_column({
+ 'name': that.name,
+ 'label': IPA.metadata[that.other_entity].label,
+ 'primary_key': true,
+ 'link': false
+ });
+ }
+
+ that.super_create(container);
+
+ var div = $('#'+that.id, container);
+
+ var buttons = $('span[name=buttons]', div);
+ if (buttons.children().length) {
+ // widget loaded from template
+ return;
+ }
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'remove',
+ 'value': 'Remove '+that.label
+ }).appendTo(buttons);
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'add',
+ 'value': 'Add '+that.label
+ }).appendTo(buttons);
+ };
+
+ that.setup = function(container) {
+
+ that.super_setup(container);
+
+ 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;
+ }
+ };
+
+ function add(container) {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var label = IPA.metadata[that.other_entity].label;
+ var title = 'Add '+label+' to '+that.entity_name+' '+pkey;
+
+ var dialog = ipa_adder_dialog({
+ 'name': '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(container);
+ dialog.close();
+ },
+ 'on_error': function() {
+ that.refresh(container);
+ dialog.close();
+ }
+ });
+
+ dialog.open();
+ }
+
+ function remove(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_deleter_dialog({
+ 'name': '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(container);
+ dialog.close();
+ },
+ 'on_error': function() {
+ that.refresh(container);
+ dialog.close();
+ }
+ });
+
+ dialog.open();
+ }
+
+ function save(container) {
+ return [];
+ }
+
+ return that;
+}
+
+function ipa_hbac_accesstime_widget(spec) {
+
+ spec = spec || {};
+
+ spec.load = spec.load || load;
+ spec.save = spec.save || save;
+
+ var that = ipa_table_widget(spec);
+
+ that.super_create = that.super('create');
+ that.super_setup = that.super('setup');
+
+ that.create = function(container) {
+
+ // create a column when none defined
+ if (!that.columns.length) {
+ that.create_column({
+ 'name': that.name,
+ 'label': that.label,
+ 'primary_key': true,
+ 'link': false
+ });
+ }
+
+ that.super_create(container);
+
+ var div = $('#'+that.id);
+
+ var buttons = $('span[name=buttons]', div);
+ if (buttons.children().length) {
+ // widget loaded from template
+ return;
+ }
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'remove',
+ 'value': 'Remove '+that.label
+ }).appendTo(buttons);
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'add',
+ 'value': 'Add '+that.label
+ }).appendTo(buttons);
+ };
+
+ function load(container, result) {
+ var values = result[that.name] || '';
+
+ if (values == '') {
+ $('input[name="'+that.name+'"][value="all"]', container).attr('checked', 'checked');
+ } else {
+ $('input[name="'+that.name+'"][value=""]', container).attr('checked', 'checked');
+ }
+
+ that.tbody.empty();
+ for (var i=0; i<values.length; i++) {
+ var tr = that.row.clone();
+ $('input[name="select"]', tr).val(values[i]);
+ $('span[name="'+that.name+'"]', tr).html(values[i]);
+ tr.appendTo(that.tbody);
+ }
+ }
+
+ function save(container) {
+ return [];
+ }
+
+ return that;
}
diff --git a/install/static/host.js b/install/static/host.js
index 8407e269d..65c2b571a 100644
--- a/install/static/host.js
+++ b/install/static/host.js
@@ -52,11 +52,14 @@ ipa_entity_set_association_definition('host', {
'rolegroup': { associator: 'serial' }
});
-function host_enrollment_status_load(container, dt, result) {
+function host_enrollment_status_load(container, result) {
// skip enrollment_status
}
-function host_usercertificate_load(container, dt, result) {
+function host_usercertificate_load(container, result) {
+
+ var dt = $('dt[title='+this.name+']', container);
+ if (!dt.length) return;
var panel = certificate_status_panel({
'entity_type': 'host',
diff --git a/install/static/index.xhtml b/install/static/index.xhtml
index bcb7cd0bb..4ba51fa38 100644
--- a/install/static/index.xhtml
+++ b/install/static/index.xhtml
@@ -12,6 +12,7 @@
<script type="text/javascript" src="jquery.ba-bbq.js"></script>
<script type="text/javascript" src="ipa.js"></script>
+ <script type="text/javascript" src="widget.js"></script>
<script type="text/javascript" src="search.js"></script>
<script type="text/javascript" src="details.js"></script>
<script type="text/javascript" src="add.js"></script>
diff --git a/install/static/ipa.css b/install/static/ipa.css
index 940a1d57b..491142d53 100644
--- a/install/static/ipa.css
+++ b/install/static/ipa.css
@@ -103,12 +103,12 @@ ul#viewtype li a {
font-weight: normal;
}
-div#details div#buttons {
+div.details div.details-buttons {
float: right;
margin-right: 15px;
}
-div#details div#buttons img {
+div.details div.details-buttons img {
border: 0;
}
@@ -131,6 +131,15 @@ hr {
margin-top: 10px;
}
+.details-section {
+ margin-left: 45px;
+ margin-right: 15px;
+ margin-top: 18px;
+ white-space: nowrap;
+ padding-bottom: 18px;
+ padding-right: 18px;
+}
+
dl.entryattrs {
clear: both;
margin-left: 15px;
@@ -226,9 +235,9 @@ span.main-separator{
-/* Search */
+/* Entity */
-.search-container{
+.entity-container{
float: left;
width: 80%;
margin: 10px;
@@ -236,6 +245,8 @@ span.main-separator{
background: #e8e8e8;
}
+/* Search */
+
.search-controls {
background:#a5a5a5;
}
diff --git a/install/static/ipa.js b/install/static/ipa.js
index 18833e677..be8e3b6ad 100644
--- a/install/static/ipa.js
+++ b/install/static/ipa.js
@@ -51,6 +51,14 @@ var IPA = ( function () {
id: 'error_dialog'
});
+ that.layout = $.bbq.getState('layout');
+ that.layouts_dir = 'layouts';
+
+ that.get_template = function(path) {
+ if (!that.layout) return path;
+ return that.layouts_dir+'/'+that.layout+'/'+path;
+ };
+
/* initialize the IPA JSON-RPC helper
* arguments:
* url - JSON-RPC URL to use (optional) */
@@ -92,9 +100,6 @@ var IPA = ( function () {
that.show_page = function (entity_name, facet_name, other_entity) {
- //var entity = IPA.get_entity(entity_name);
- //var facet = entity.get_facet(facet_name);
-
var state = {};
state[entity_name + '-facet'] = facet_name;
state[entity_name + '-enroll'] = other_entity ? other_entity : '';
diff --git a/install/static/layouts/Makefile.am b/install/static/layouts/Makefile.am
new file mode 100644
index 000000000..9e1ee7b74
--- /dev/null
+++ b/install/static/layouts/Makefile.am
@@ -0,0 +1,22 @@
+AUTOMAKE_OPTIONS = 1.7
+
+NULL =
+
+SUBDIRS = \
+ default \
+ $(NULL)
+
+appdir = $(IPA_DATA_DIR)/static/layouts
+app_DATA = \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(app_DATA) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
+ $(NULL)
+
+distclean:
diff --git a/install/static/layouts/default/Makefile.am b/install/static/layouts/default/Makefile.am
new file mode 100644
index 000000000..904fad171
--- /dev/null
+++ b/install/static/layouts/default/Makefile.am
@@ -0,0 +1,25 @@
+AUTOMAKE_OPTIONS = 1.7
+
+NULL =
+
+SUBDIRS = \
+ $(NULL)
+
+appdir = $(IPA_DATA_DIR)/static/layouts/default
+app_DATA = \
+ hbac-details-accesstime.html \
+ hbac-details-general.html \
+ hbac-details-host.html \
+ hbac-details-service.html \
+ hbac-details-sourcehost.html \
+ hbac-details-user.html \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(app_DATA) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
+ $(NULL)
diff --git a/install/static/layouts/default/hbac-details-accesstime.html b/install/static/layouts/default/hbac-details-accesstime.html
new file mode 100755
index 000000000..4122c76a6
--- /dev/null
+++ b/install/static/layouts/default/hbac-details-accesstime.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>When</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ Rule applies when access is being requested at:
+ <input type="radio" name="accesstime" value="all"/>Any Time
+ <input type="radio" name="accesstime" value=""/>Specified Times
+ <br/>
+
+ <div id="hbac-accesstime">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Access Time</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Access Times"/>
+ <input type="button" name="add" value="Add Access Times"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="time"/>
+ </td>
+ <td>
+ <span name="accesstime">time</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/static/layouts/default/hbac-details-general.html b/install/static/layouts/default/hbac-details-general.html
new file mode 100755
index 000000000..81b2a4ae6
--- /dev/null
+++ b/install/static/layouts/default/hbac-details-general.html
@@ -0,0 +1,45 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>General</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ <table style="width: 100%; border: 0 solid black;">
+ <tr>
+ <td style="width: 100px; text-align: right;">
+ Name:
+ </td>
+ <td>
+ <input type="text" name="cn" size="30"/>
+ </td>
+ <td style="text-align: right;">
+ Rule type:
+ <input type="radio" name="accessruletype" value="allow"/>Allow
+ <input type="radio" name="accessruletype" value="deny"/>Deny
+ </td>
+ </tr>
+ <tr>
+ <td style="text-align: right; vertical-align: top;">
+ Description:
+ </td>
+ <td colspan="2">
+ <textarea name="description" rows="5" style="width: 100%;" cols="40"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td style="text-align: right; vertical-align: top;">
+ Rule status:
+ </td>
+ <td colspan="2">
+ <input type="radio" name="ipaenabledflag" value="TRUE"/>Active
+ <input type="radio" name="ipaenabledflag" value="FALSE"/>Inactive
+ </td>
+ </tr>
+ </table>
+</div>
+</body>
+</html>
diff --git a/install/static/layouts/default/hbac-details-host.html b/install/static/layouts/default/hbac-details-host.html
new file mode 100755
index 000000000..a20e8115a
--- /dev/null
+++ b/install/static/layouts/default/hbac-details-host.html
@@ -0,0 +1,75 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Accessing</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ Rule applies when access is requested to:
+ <input type="radio" name="hostcategory" value="all"/>Any Host
+ <input type="radio" name="hostcategory" value=""/>Specified Hosts and Groups
+ <br/>
+
+ <div id="hbac-memberhost_host">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Host</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Hosts"/>
+ <input type="button" name="add" value="Add Hosts"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="host"/>
+ </td>
+ <td>
+ <span name="memberhost_host">host</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div id="hbac-memberhost_hostgroup">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Host Group</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Host Groups"/>
+ <input type="button" name="add" value="Add Host Groups"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="hostgroups"/>
+ </td>
+ <td>
+ <span name="memberhost_hostgroup">hostgroups</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/static/layouts/default/hbac-details-service.html b/install/static/layouts/default/hbac-details-service.html
new file mode 100755
index 000000000..380cb1bb4
--- /dev/null
+++ b/install/static/layouts/default/hbac-details-service.html
@@ -0,0 +1,75 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Via Service</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ Rule applies when access is requested via:
+ <input type="radio" name="servicecategory" value="all"/>Any Service
+ <input type="radio" name="servicecategory" value=""/>Specified Services and Groups
+ <br/>
+
+ <div id="hbac-memberservice_hbacsvc">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Service</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Services"/>
+ <input type="button" name="add" value="Add Services"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="service"/>
+ </td>
+ <td>
+ <span name="memberservice_hbacsvc">service</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div id="hbac-memberservice_hbacsvcgroup">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Service Group</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Service Groups"/>
+ <input type="button" name="add" value="Add Service Groups"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="services"/>
+ </td>
+ <td>
+ <span name="memberservice_hbacsvcgroup">services</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/static/layouts/default/hbac-details-sourcehost.html b/install/static/layouts/default/hbac-details-sourcehost.html
new file mode 100755
index 000000000..12e934c0d
--- /dev/null
+++ b/install/static/layouts/default/hbac-details-sourcehost.html
@@ -0,0 +1,75 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>From</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ Rule applies when access is being initiated from:
+ <input type="radio" name="sourcehostcategory" value="all"/>Any Host
+ <input type="radio" name="sourcehostcategory" value=""/>Specified Hosts and Groups
+ <br/>
+
+ <div id="hbac-sourcehost_host">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Host</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Hosts"/>
+ <input type="button" name="add" value="Add Hosts"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="host"/>
+ </td>
+ <td>
+ <span name="sourcehost_host">host</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div id="hbac-sourcehost_hostgroup">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Host Group</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Host Groups"/>
+ <input type="button" name="add" value="Add Host Groups"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="hosts"/>
+ </td>
+ <td>
+ <span name="sourcehost_hostgroup">hosts</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/static/layouts/default/hbac-details-user.html b/install/static/layouts/default/hbac-details-user.html
new file mode 100755
index 000000000..ef41b6f8d
--- /dev/null
+++ b/install/static/layouts/default/hbac-details-user.html
@@ -0,0 +1,75 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Who</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ Rule applies when access is requested by:
+ <input type="radio" name="usercategory" value="all"/>Anyone
+ <input type="radio" name="usercategory" value=""/>Specified Users and Groups
+ <br/>
+
+ <div id="hbac-memberuser_user">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">User</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Users"/>
+ <input type="button" name="add" value="Add Users"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="user"/>
+ </td>
+ <td>
+ <span name="memberuser_user">user</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div id="hbac-memberuser_group">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">User Group</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove User Groups"/>
+ <input type="button" name="add" value="Add User Groups"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="users"/>
+ </td>
+ <td>
+ <span name="memberuser_group">users</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/static/navigation.js b/install/static/navigation.js
index 72b58ee09..0434f58ca 100644
--- a/install/static/navigation.js
+++ b/install/static/navigation.js
@@ -51,8 +51,10 @@ function nav_create(nls, container, tabclass)
var tabs = $('.' + tabclass);
tabs.tabs({
select: function(event, ui) {
+ var panel = $(ui.panel);
+ var parent = panel.parent();
+ var id = parent.attr('id');
var state = {};
- var id = $(ui.panel).parent().attr('id');
state[id] = ui.index;
nav_push_state(state);
return true;
@@ -87,6 +89,8 @@ function nav_generate_tabs(nls, container, tabclass, depth)
if (tab.children) {
nav_generate_tabs(tab.children, div, tabclass, depth +1 );
} else {
+ div.addClass('entity-container');
+
var entity = ipa_get_entity(tab.name);
entity.label = tab.label;
entity.setup = tab.setup;
diff --git a/install/static/policy.js b/install/static/policy.js
index dd5447718..f0fa0cd9a 100644
--- a/install/static/policy.js
+++ b/install/static/policy.js
@@ -259,7 +259,6 @@ function ipa_records_facet(spec){
that.setup_views(container);
container.attr('title', that.entity_name);
- container.addClass('search-container');
var h2 = $('<h2></h2>',{
text: "Records for DNS Zone:" + that.pkey
@@ -291,15 +290,23 @@ function ipa_records_facet(spec){
//}));
- ipa_make_button('ui-icon-search', IPA.messages.button.find).
- click(function(){load(container)}).appendTo(control_span);
+ ipa_button({
+ 'label': IPA.messages.button.find,
+ 'icon': 'ui-icon-search',
+ 'click': function(){load(container)}
+ }).appendTo(control_span);
- ipa_make_button('ui-icon-plus', IPA.messages.button.add).
- click(add_click).appendTo(control_span);
+ ipa_button({
+ 'label': IPA.messages.button.add,
+ 'icon': 'ui-icon-plus',
+ 'click': add_click
+ }).appendTo(control_span);
- ipa_make_button('ui-icon-trash', IPA.messages.button.delete).
- click(function(){delete_records(records_table);}).
- appendTo(control_span);
+ ipa_button({
+ 'label': IPA.messages.button.delete,
+ 'icon': 'ui-icon-trash',
+ 'click': function(){delete_records(records_table);}
+ }).appendTo(control_span);
div.append('<span class="records-buttons"></span>');
@@ -416,7 +423,7 @@ function ipa_records_facet(spec){
//TODO this is cut and pasted from search, we need to unify
function display(obj_name, data){
- var selector = '.search-container[title=' + obj_name + ']';
+ var selector = '.entity-container[title=' + obj_name + ']';
var thead = $(selector + ' thead');
var tbody = $(selector + ' tbody');
var tfoot = $(selector + ' tfoot');
diff --git a/install/static/search.js b/install/static/search.js
index 62fffbe99..508f6ed40 100644
--- a/install/static/search.js
+++ b/install/static/search.js
@@ -25,14 +25,10 @@ function ipa_search_column(spec) {
spec = spec || {};
- var that = {};
+ spec.init = spec.init || init;
+ spec.setup = spec.setup || setup;
- that.name = spec.name;
- that.label = spec.label || that.name;
- that.facet = spec.facet;
-
- that.init = spec.init || init;
- that.setup = spec.setup || setup;
+ var that = ipa_column_widget(spec);
function init() {
}
@@ -56,6 +52,18 @@ function ipa_search_facet(spec) {
that.columns = [];
that.columns_by_name = {};
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+
+ for (var i=0; i<that.columns.length; i++) {
+ that.columns[i].entity_name = entity_name;
+ }
+ });
+
that.get_columns = function() {
return that.columns;
};
@@ -65,12 +73,12 @@ function ipa_search_facet(spec) {
};
that.add_column = function(column) {
+ column.entity_name = that.entity_name;
that.columns.push(column);
that.columns_by_name[column.name] = column;
};
that.create_column = function(spec) {
- spec.facet = that;
var column = ipa_search_column(spec);
that.add_column(column);
return column;
@@ -90,8 +98,10 @@ function ipa_search_facet(spec) {
search_create(that.entity_name, that.columns, container);
- ipa_make_button('ui-icon-plus', IPA.messages.button.add).
- click(function() {
+ ipa_button({
+ 'label': IPA.messages.button.add,
+ 'icon': 'ui-icon-plus',
+ 'click': function() {
var entity = IPA.get_entity(that.entity_name);
if (entity) {
entity.add_dialog.open();
@@ -102,8 +112,8 @@ function ipa_search_facet(spec) {
dialog.open();
return false;
- }).
- appendTo($('.search-controls', container));
+ }
+ }).appendTo($('.search-controls', container));
search_load(container, that.filter);
}
@@ -183,7 +193,6 @@ function search_create(entity_name, columns, container) {
}
container.attr('title', entity_name);
- container.addClass('search-container');
var search_controls = $('<div/>', {
'class': 'search-controls'
@@ -198,11 +207,17 @@ function search_create(entity_name, columns, container) {
'name': 'search-' + entity_name + '-filter'
}).appendTo(search_filter);
- ipa_make_button('ui-icon-search', IPA.messages.button.find).
- click(find_on_click).appendTo(search_filter);
+ ipa_button({
+ 'label': IPA.messages.button.find,
+ 'icon': 'ui-icon-search',
+ 'click': find_on_click
+ }).appendTo(search_filter);
- ipa_make_button('ui-icon-trash',IPA.messages.button.delete).
- click(delete_on_click_outer).appendTo(search_filter);
+ ipa_button({
+ 'label': IPA.messages.button.delete,
+ 'icon': 'ui-icon-trash',
+ 'click': delete_on_click_outer
+ }).appendTo(search_filter);
search_controls.append('<span class="search-buttons"></span>');
@@ -231,20 +246,17 @@ function search_insert_checkbox_th(jobj)
function select_all_on_click() {
var jobj = $(this);
- var checked = null;
- if (jobj.attr('checked')) {
- checked = true;
+ var checked = jobj.is(':checked');
+ if (checked) {
jobj.attr('title', 'Unselect All');
} else {
- checked = false;
jobj.attr('title', 'Select All');
}
- jobj.attr('checked', checked);
- var chks = jobj.closest('.search-container').find('.search-selector');
+ var chks = jobj.closest('.entity-container').find('.search-selector').get();
for (var i = 0; i < chks.length; ++i)
chks[i].checked = checked;
- };
+ }
var checkbox = $('<input />', {
type: 'checkbox',
@@ -307,7 +319,7 @@ function search_load(container, criteria, on_win, on_fail)
function search_generate_tr(thead, tbody, entry_attrs)
{
- var obj_name = tbody.closest('.search-container').attr('title');
+ var obj_name = tbody.closest('.entity-container').attr('title');
var pkey = IPA.metadata[obj_name].primary_key;
var pkey_value = entry_attrs[pkey];
@@ -368,7 +380,7 @@ var _search_a_pkey_template = '<a href="jslink" class="search-a-pkey">V</a>';
function search_generate_td(tr, attr, value, entry_attrs)
{
- var obj_name = tr.closest('.search-container').attr('title');
+ var obj_name = tr.closest('.entity-container').attr('title');
var param_info = ipa_get_param_info(obj_name, attr);
if (param_info && param_info['primary_key'])
@@ -379,7 +391,7 @@ function search_generate_td(tr, attr, value, entry_attrs)
function search_display(obj_name, data)
{
- var selector = '.search-container[title=' + obj_name + ']';
+ var selector = '.entity-container[title=' + obj_name + ']';
var thead = $(selector + ' thead');
var tbody = $(selector + ' tbody');
var tfoot = $(selector + ' tfoot');
diff --git a/install/static/service.js b/install/static/service.js
index 21b2d0b92..1b467cb59 100644
--- a/install/static/service.js
+++ b/install/static/service.js
@@ -126,36 +126,45 @@ function service_add_krbprincipalname(add_dialog, mode) {
}
ipa_entity_set_association_definition('service', {
- 'host': { method: 'add_host' }
+ 'host': { add_method: 'add_host', delete_host: 'remove_host' }
});
-function service_krbprincipalname_setup(container, dl, section) {
+function service_krbprincipalname_setup(container) {
// skip krbprincipalname
}
-function service_krbprincipalname_load(container, dt, result) {
+function service_krbprincipalname_load(container, result) {
// skip krbprincipalname
}
-function service_service_load(container, dt, result) {
+function service_service_load(container, result) {
+ var dt = $('dt[title='+this.name+']', container);
+ if (!dt.length) return;
+
var krbprincipalname = result['krbprincipalname'][0];
var service = krbprincipalname.replace(/\/.*$/, '');
var dd = ipa_create_first_dd(this.name, service);
dt.after(dd);
}
-function service_host_load(container, dt, result) {
+function service_host_load(container, result) {
+ var dt = $('dt[title='+this.name+']', container);
+ if (!dt.length) return;
+
var krbprincipalname = result['krbprincipalname'][0];
var host = krbprincipalname.replace(/^.*\//, '').replace(/@.*$/, '');
var dd = ipa_create_first_dd(this.name, host);
dt.after(dd);
}
-function service_provisioning_status_load(container, dt, result) {
+function service_provisioning_status_load(container, result) {
// skip provisioning_status
}
-function service_usercertificate_load(container, dt, result) {
+function service_usercertificate_load(container, result) {
+
+ var dt = $('dt[title='+this.name+']', container);
+ if (!dt.length) return;
var panel = certificate_status_panel({
'entity_type': 'service',
diff --git a/install/static/test/all_tests.html b/install/static/test/all_tests.html
index 50c5155dc..64412b01b 100644
--- a/install/static/test/all_tests.html
+++ b/install/static/test/all_tests.html
@@ -8,6 +8,7 @@
<script type="text/javascript" src="../jquery.ba-bbq.js"></script>
<script type="text/javascript" src="../jquery-ui.js"></script>
<script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../widget.js"></script>
<script type="text/javascript" src="../details.js"></script>
<script type="text/javascript" src="../search.js"></script>
<script type="text/javascript" src="../add.js"></script>
diff --git a/install/static/test/association_tests.js b/install/static/test/association_tests.js
index 05e43ce4a..9f49abf73 100644
--- a/install/static/test/association_tests.js
+++ b/install/static/test/association_tests.js
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-test("Testing serial_associate().", function() {
+test("Testing serial_associator().", function() {
expect(10);
@@ -26,25 +26,25 @@ test("Testing serial_associate().", function() {
var counter = 0;
- var form = {
+ var params = {
method: "add_member",
pkey: "test",
- oneObj: "user",
- manyObj: "group"
+ entity_name: "user",
+ other_entity: "group"
};
- var manyObjPkeys = ['user1', 'user2', 'user3'];
+ params.values = ['user1', 'user2', 'user3'];
ipa_cmd = function(name, args, options, win_callback, fail_callback, objname) {
counter++;
equals(
- name, form.method,
+ name, params.method,
"Checking ipa_cmd() parameter: method"
);
equals(
- objname, form.manyObj,
+ objname, params.other_entity,
"Checking ipa_cmd() parameter: object name"
);
@@ -58,17 +58,17 @@ test("Testing serial_associate().", function() {
return 0;
};
- var on_success = function() {
+ params.on_success = function() {
ok(true, "on_success() is invoked.");
};
- var associator = serial_associate(form, manyObjPkeys, on_success);
- //associator.associateNext();
+ var associator = serial_associator(params);
+ associator.execute();
ipa_cmd = orig_ipa_cmd;
});
-test("Testing BulkAssociator().", function() {
+test("Testing bulk_associator().", function() {
expect(5);
@@ -76,36 +76,36 @@ test("Testing BulkAssociator().", function() {
var counter = 0;
- var form = {
+ var params = {
method: "add_member",
pkey: "test",
- oneObj: "user",
- manyObj: "group"
+ entity_name: "user",
+ other_entity: "group"
};
- var manyObjPkeys = ['user1', 'user2', 'user3'];
+ params.values = ['user1', 'user2', 'user3'];
ipa_cmd = function(name, args, options, win_callback, fail_callback, objname) {
counter++;
equals(
- name, form.method,
+ name, params.method,
"Checking ipa_cmd() parameter: method"
);
equals(
- objname, form.oneObj,
+ objname, params.entity_name,
"Checking ipa_cmd() parameter: object name"
);
equals(
- args[0], form.pkey,
+ args[0], params.pkey,
"Checking ipa_cmd() parameter: primary key"
);
equals(
- options[form.manyObj], "user1,user2,user3",
- "Checking ipa_cmd() parameter: options[\""+form.manyObj+"\"]"
+ options[params.other_entity], "user1,user2,user3",
+ "Checking ipa_cmd() parameter: options[\""+params.other_entity+"\"]"
);
var response = {};
@@ -113,12 +113,12 @@ test("Testing BulkAssociator().", function() {
return 0;
};
- var on_success = function() {
+ params.on_success = function() {
ok(true, "on_success() is invoked.");
};
- var associator = bulk_associate(form, manyObjPkeys, on_success);
- //associator.associateNext();
+ var associator = bulk_associator(params);
+ associator.execute();
ipa_cmd = orig_ipa_cmd;
});
diff --git a/install/static/test/details_tests.html b/install/static/test/details_tests.html
index e96fa4b72..3cb20c562 100644
--- a/install/static/test/details_tests.html
+++ b/install/static/test/details_tests.html
@@ -8,6 +8,7 @@
<script type="text/javascript" src="../jquery.ba-bbq.js"></script>
<script type="text/javascript" src="../jquery-ui.js"></script>
<script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../widget.js"></script>
<script type="text/javascript" src="../details.js"></script>
<script type="text/javascript" src="../entity.js"></script>
diff --git a/install/static/test/details_tests.js b/install/static/test/details_tests.js
index 4a60216ef..8482f6df0 100644
--- a/install/static/test/details_tests.js
+++ b/install/static/test/details_tests.js
@@ -19,45 +19,96 @@
*/
-test("Testing ipa_details_create().", function() {
+test("Testing ipa_details_section.setup().", function() {
- var name = 'NAMENAMENAME';
- var identity = 'IDIDID';
+ IPA.ajax_options.async = false;
+
+ IPA.init(
+ "data",
+ true,
+ function(data, text_status, xhr) {
+ ok(true, "ipa_init() succeeded.");
+ },
+ function(xhr, text_status, error_thrown) {
+ ok(false, "ipa_init() failed: "+error_thrown);
+ }
+ );
+
+ var result = {};
- var section = ipa_stanza({name:identity, label:name}).
+ var section = ipa_stanza({name:'IDIDID', label:'NAMENAMENAME'}).
input({name:'cn', label:'Entity Name'}).
input({name:'description', label:'Description'}).
input({name:'number', label:'Entity ID'});
- var details = section.fields;
- var parent = $("<div/>");
- var container = $("<div title='entity'/>");
- parent.append(container);
- ipa_details_section_setup(parent,container, section);
+ var fields = section.fields;
+ var container = $("<div/>");
+ section.setup(container, result);
- ok(parent.find('hr').length);
+ var dl = container.find('dl');
- var h2= parent.find('h2');
- ok(h2.length);
- ok(h2[0].innerHTML.indexOf(name) > 1,"find name in html");
+ same(
+ dl.length, 1,
+ 'Checking dl tag'
+ );
+
+ same(
+ dl.attr('id'), section.name,
+ 'Checking section name'
+ );
+
+ var dts = $('dt', dl);
+ same(
+ dts.length, fields.length, // each field generates dt & dd
+ 'Checking number of children'
+ );
+
+ for (var i=0; i<fields.length; i++) {
+ var dt = dts.get(i);
+ same(
+ dt.title, fields[i].name,
+ 'Checking field '+i+'\'s title'
+ );
+
+ same(
+ dt.innerHTML, fields[i].label+':',
+ 'Checking field '+i+'\'s label'
+ );
+ }
+});
- var dl = parent.find('dl');
- ok(dl.length);
- same(dl[0].children.length,3,"children tag count");
- same(dl[0].id, identity,"identity");
- same(details[0].name, dl[0].children[0].title,"name");
- var d = dl[0].children[0].innerHTML;
- same(details[0].label+":",d);
- same(details[2].name,dl[0].children[2].title);
- d = dl[0].children[2].innerHTML;
- same(details[2].label+":" ,d);
-});
+test("Testing details lifecycle: create, save ().", function(){
+ IPA.ajax_options.async = false;
-test("Testing details lifecycle:setup, load, save ().", function(){
+ IPA.init(
+ "data",
+ true,
+ function(data, text_status, xhr) {
+ ok(true, "ipa_init() succeeded.");
+ },
+ function(xhr, text_status, error_thrown) {
+ ok(false, "ipa_init() failed: "+error_thrown);
+ }
+ );
+
+ var result = {};
+
+ ipa_cmd(
+ 'user_show',
+ ['kfrog'],
+ {},
+ function(data, text_status, xhr) {
+ result = data.result.result;
+ ok(true, "ipa_cmd() succeeded.");
+ },
+ function(xhr, text_status, error_thrown) {
+ ok(false, "ipa_cmd() failed: "+error_thrown);
+ }
+ );
var setup_status_called = false;
var save_password_called= false;
@@ -82,6 +133,7 @@ test("Testing details lifecycle:setup, load, save ().", function(){
function setup_st(){
}
+
var container = $("<div/>");
var obj_name = 'user';
ipa_entity_set_details_definition(obj_name, [
@@ -116,46 +168,42 @@ test("Testing details lifecycle:setup, load, save ().", function(){
var entity = ipa_get_entity(obj_name);
var facet = entity.get_facet('details');
- var sections = facet.get_sections();
- ipa_details_create(container, sections);
+ facet.create(container, result);
var contact = container.find('dl#contact.entryattrs');
- ok(contact);
- var identity = container.find('dl#identity.entryattrs');
- ok(identity);
- var dts= identity.find('dt');
- ok(dts);
- same(6, dts.length);
- same('initials',dts[5].title);
- //TODO extract into Fixture
- IPA.ajax_options.async = false;
- $.ajaxSetup(IPA.ajax_options);
- IPA.json_url = './data';
- IPA.use_static_files = true;
-
- container.attr('id','user');
-
- ok (setup_status_called , 'setup status called');
+ ok(
+ contact,
+ 'dl tag for contact is created'
+ );
+ var identity = container.find('dl#identity.entryattrs');
- ipa_details_load(container,
- 'kfrog',
- function(){load_success_called = true},
- function(){load_failure_called = true});
+ ok(
+ identity,
+ 'dl tag for identity is created'
+ );
- ok (load_success_called,'load success called');
- ok (!load_failure_called,'load failure not called');
+ var dts= identity.find('dt');
+ same(
+ dts.length, 6,
+ 'Checking dt tags for identity'
+ );
- ok (load_manager_called, 'load manager called');
+ same(
+ dts[5].title, facet.get_sections()[0].get_fields()[5].name,
+ 'Checking dt title'
+ );
+ container.attr('id','user');
- ipa_details_load(container,
- 'kfrog',
- function(){load_success_called = true},
- function(){load_failure_called = true});
+ ok (
+ setup_status_called,
+ 'Setup status called'
+ );
+ ok (load_manager_called, 'load manager called');
ipa_details_update(container,
'kfrog',
@@ -183,34 +231,3 @@ test("Testing _ipa_create_text_input().", function(){
same(text[0].value,value );
same(text[0].type,"text" );
});
-
-
-test("Testing ipa_details_section_setup()",function(){
-
- var section = ipa_stanza({name: 'IDIDID', label: 'NAMENAMENAME'}).
- input({name:'cn', label:'Entity Name'}).
- input({name:'description', label:'Description'}).
- input({name:'number', label:'Entity ID'});
- var fields = section.fields;
- var container = $("<div title='entity'/>");
- var details = $("<div/>");
- container.append(details);
-
- ipa_details_section_setup(container, details, section);
-
- ok(container.find('hr'));
-
- var h2= container.find('h2');
- ok(h2);
- ok(h2[0].innerHTML.indexOf(section.label) > 1,"find name in html");
-
- var dl = container.find('dl');
- ok(dl);
- same(dl[0].children.length,3);
- same(dl[0].id, section.name);
- same(dl[0].children[0].title, fields[0].name);
- same(dl[0].children[0].innerHTML, fields[0].label+":");
- same(dl[0].children[2].title, fields[2].name);
- same(dl[0].children[2].innerHTML, fields[2].label+":");
-
-});
diff --git a/install/static/test/entity_tests.html b/install/static/test/entity_tests.html
index 0f7962952..cd6b64095 100644
--- a/install/static/test/entity_tests.html
+++ b/install/static/test/entity_tests.html
@@ -7,6 +7,7 @@
<script type="text/javascript" src="../jquery.js"></script>
<script type="text/javascript" src="../jquery.ba-bbq.js"></script>
<script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../widget.js"></script>
<script type="text/javascript" src="../details.js"></script>
<script type="text/javascript" src="../search.js"></script>
<script type="text/javascript" src="../add.js"></script>
diff --git a/install/static/test/entity_tests.js b/install/static/test/entity_tests.js
index cc43b8798..08fc3111d 100644
--- a/install/static/test/entity_tests.js
+++ b/install/static/test/entity_tests.js
@@ -170,7 +170,7 @@ test('Testing ipa_entity_quick_links().', function() {
var container = $('<div/>', {
title: obj_name,
- class: 'search-container'
+ class: 'entity-container'
});
var search_table = $('<table/>', {
diff --git a/install/static/test/navigation_tests.html b/install/static/test/navigation_tests.html
index fa911d6e6..16d095aca 100644
--- a/install/static/test/navigation_tests.html
+++ b/install/static/test/navigation_tests.html
@@ -7,6 +7,8 @@
<script type="text/javascript" src="../jquery.js"></script>
<script type="text/javascript" src="../jquery.ba-bbq.js"></script>
<script type="text/javascript" src="../jquery-ui.js"></script>
+ <script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../entity.js"></script>
<script type="text/javascript" src="../navigation.js"></script>
<script type="text/javascript" src="navigation_tests.js"></script>
</head>
diff --git a/install/static/user.js b/install/static/user.js
index 5645967d2..1b6054d7e 100644
--- a/install/static/user.js
+++ b/install/static/user.js
@@ -151,8 +151,10 @@ function on_lock_win(data, textStatus, xhr)
/* ATTRIBUTE CALLBACKS */
var toggle_temp = 'S <a href="jslink" onclick="return (toggle_on_click(this))" title="S">Toggle</a>';
-function user_status_load(container, dt, result)
-{
+function user_status_load(container, result) {
+ var dt = $('dt[title='+this.name+']', container);
+ if (!dt.length) return;
+
var memberof = result['memberof'];
var dd;
@@ -223,8 +225,10 @@ function resetpwd_on_click(){
return false;
}
-function user_password_load(container, dt, result)
-{
+function user_password_load(container, result) {
+ var dt = $('dt[title='+this.name+']', container);
+ if (!dt.length) return;
+
dt.after(ipa_create_first_dd(
this.name,
$('<a/>',{
@@ -245,8 +249,10 @@ var states = [
'PA', 'PR', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VI', 'VA',
'WA', 'WV', 'WI', 'WY', ''
];
-function user_state_load(container, dt, result)
-{
+function user_state_load(container, result) {
+ var dt = $('dt[title='+this.name+']', container);
+ if (!dt.length) return;
+
var next = dt.next();
next.css('clear', 'none');
next.css('width', '70px');
diff --git a/install/static/widget.js b/install/static/widget.js
new file mode 100755
index 000000000..bf893e042
--- /dev/null
+++ b/install/static/widget.js
@@ -0,0 +1,473 @@
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 only
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* REQUIRES: ipa.js */
+
+function ipa_widget(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.id = spec.id;
+ that.name = spec.name;
+ that.label = spec.label;
+ that.read_only = spec.read_only;
+ that._entity_name = spec.entity_name;
+
+ that.create = spec.create || create;
+ that.setup = spec.setup || setup;
+ that.load = spec.load || load;
+ that.save = spec.save || save;
+
+ that.super = function(name) {
+ var method = that[name];
+ return function () {
+ return method.apply(that, arguments);
+ };
+ };
+
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+ });
+
+ function create(container) {
+ }
+
+ function setup(container) {
+ }
+
+ function load(container, result) {
+ }
+
+ function save(container) {
+ return [];
+ }
+
+ return that;
+}
+
+function ipa_text_widget(spec) {
+
+ spec = spec || {};
+
+ spec.setup = spec.setup || setup;
+ spec.load = spec.load || load;
+ spec.save = spec.save || save;
+
+ var that = ipa_widget(spec);
+
+ function setup(container) {
+ }
+
+ function load(container, result) {
+ that.value = result[that.name] || '';
+ var input = $('input[name="'+that.name+'"]', container);
+
+ var param_info = ipa_get_param_info(that.entity_name, that.name);
+ if (param_info.primary_key) {
+ input.replaceWith($('<label/>', { 'html': that.value.toString() }));
+
+ } else {
+ input.val(that.value);
+ }
+ }
+
+ function save(container) {
+ var values = [];
+
+ if (that.value) {
+ values.push(that.value);
+
+ } else {
+ var input = $('input[name="'+that.name+'"]', container);
+ values.push(input.val());
+ }
+
+ return values;
+ }
+
+ return that;
+}
+
+function ipa_radio_widget(spec) {
+
+ spec = spec || {};
+
+ spec.setup = spec.setup || setup;
+ spec.load = spec.load || load;
+ spec.save = spec.save || save;
+
+ var that = ipa_widget(spec);
+
+ function setup(container) {
+ }
+
+ function load(container, result) {
+ var value = result[that.name] || '';
+ $('input[name="'+that.name+'"][value="'+value+'"]', container).attr('checked', 'checked');
+ }
+
+ function save(container) {
+ var values = [];
+
+ var value = $('input[name="'+that.name+'"]:checked', container).val();
+ values.push(value);
+
+ return values;
+ }
+
+ return that;
+}
+
+function ipa_textarea_widget(spec) {
+
+ spec = spec || {};
+
+ spec.setup = spec.setup || setup;
+ spec.load = spec.load || load;
+ spec.save = spec.save || save;
+
+ var that = ipa_widget(spec);
+
+ function setup(container) {
+ }
+
+ function load(container, result) {
+ var value = result[that.name] || '';
+ $('textarea[name="'+that.name+'"]', container).val(value);
+ }
+
+ function save(container) {
+ var values = [];
+
+ var value = $('textarea[name="'+that.name+'"]', container).val();
+ values.push(value);
+
+ return values;
+ }
+
+ return that;
+}
+
+function ipa_button_widget(spec) {
+
+ spec = spec || {};
+
+ spec.setup = spec.setup || setup;
+ spec.load = spec.load || load;
+ spec.save = spec.save || save;
+
+ var that = ipa_widget(spec);
+
+ that.click = spec.click;
+
+ function setup(container) {
+ var input = $('[name="'+that.name+'"]', container);
+ input.replaceWith(ipa_button({ 'label': that.label, 'click': that.click }));
+ }
+
+ function load(container, result) {
+ }
+
+ function save(container) {
+ var values = [];
+ return values;
+ }
+
+ return that;
+}
+
+function ipa_column_widget(spec) {
+
+ spec = spec || {};
+
+ var that = ipa_widget(spec);
+
+ that.primary_key = spec.primary_key;
+ that.link = spec.link;
+
+ return that;
+}
+
+function ipa_table_widget(spec) {
+
+ spec = spec || {};
+
+ spec.create = spec.create || create;
+ spec.setup = spec.setup || setup;
+ spec.load = spec.load || load;
+ spec.save = spec.save || save;
+
+ var that = ipa_widget(spec);
+
+ that.add = spec.add;
+ that.remove = spec.remove;
+
+ that.columns = [];
+ that.columns_by_name = {};
+
+ that.get_columns = function() {
+ return that.columns;
+ };
+
+ that.get_column = function(name) {
+ return that.columns_by_name[name];
+ };
+
+ that.add_column = function(column) {
+ column.entity_name = that.entity_name;
+ that.columns.push(column);
+ that.columns_by_name[column.name] = column;
+ };
+
+ that.create_column = function(spec) {
+ var column = ipa_column_widget(spec);
+ that.add_column(column);
+ return column;
+ };
+
+ function create(container) {
+
+ var div = $('#'+that.id, container);
+ if (div.children().length) {
+ // widget loaded from template
+ return;
+ }
+
+ div.empty();
+
+ var table = $('<table/>', {
+ 'class': 'search-table'
+ }).appendTo(div);
+
+ var thead = $('<thead/>').appendTo(table);
+
+ var tr = $('<tr/>').appendTo(thead);
+
+ var th = $('<th/>', {
+ 'style': 'width: 25px;'
+ }).appendTo(tr);
+
+ $('<input/>', {
+ 'type': 'checkbox',
+ 'name': 'select'
+ }).appendTo(th);
+
+ for (var i=0; i<that.columns.length; i++) {
+ th = $('<th/>').appendTo(tr);
+
+ $('<span/>', {
+ 'style': 'float: left;',
+ 'html': that.columns[i].label
+ }).appendTo(th);
+
+ if (i == that.columns.length-1) {
+ $('<span/>', {
+ 'name': 'buttons',
+ 'style': 'float: right;'
+ }).appendTo(th);
+ }
+ }
+
+ var tbody = $('<tbody/>').appendTo(table);
+
+ tr = $('<tr/>').appendTo(tbody);
+
+ var td = $('<td/>').appendTo(tr);
+
+ $('<input/>', {
+ 'type': 'checkbox',
+ 'name': 'select',
+ 'value': 'user'
+ }).appendTo(td);
+
+ for (var i=0; i<that.columns.length; i++) {
+ td = $('<td/>').appendTo(tr);
+
+ $('<span/>', {
+ 'name': that.columns[i].name
+ }).appendTo(td);
+ }
+ }
+
+ function setup(container) {
+ var div = $('#'+that.id, container);
+ that.table = $('table', div);
+ that.thead = $('thead', that.table);
+ that.tbody = $('tbody', that.table);
+
+ var select_all_checkbox = $('input[name=select]', that.thead);
+ select_all_checkbox.attr('title', 'Select All');
+
+ select_all_checkbox.click(function() {
+ var checked = select_all_checkbox.is(':checked');
+ select_all_checkbox.attr('title', checked ? 'Unselect All' : 'Select All');
+ var checkboxes = $('input[name=select]', that.tbody).get();
+ for (var i=0; i<checkboxes.length; i++) {
+ checkboxes[i].checked = checked;
+ }
+ });
+
+ var button = $('input[name=remove]', that.table);
+ button.replaceWith(ipa_button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-trash',
+ 'click': function() { that.remove(container); }
+ }));
+
+ button = $('input[name=add]', that.table);
+ button.replaceWith(ipa_button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-plus',
+ 'click': function() { that.add(container) }
+ }));
+
+ that.row = that.tbody.children().first();
+ that.row.detach();
+ }
+
+ function load(container, result) {
+
+ that.tbody.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(container, record);
+ }
+ }
+
+ function save(container) {
+ var values = [];
+
+ $('input[name="select"]', that.tbody).each(function() {
+ values.push($(this).val());
+ });
+
+ return values;
+ }
+
+ that.get_selected_values = function(container) {
+ var values = [];
+
+ $('input[name="select"]:checked', that.tbody).each(function() {
+ values.push($(this).val());
+ });
+
+ return values;
+ };
+
+ that.get_record = function(result, index) {
+ var record = {};
+ for (var i=0; i<that.columns.length; i++){
+ var name = that.columns[i].name;
+ record[name] = result[name][index];
+ }
+ return record;
+ };
+
+ that.add_row = function(container, record) {
+
+ var tr = that.row.clone();
+ tr.appendTo(that.tbody);
+
+ for (var i=0; i<that.columns.length; i++){
+ var column = that.columns[i];
+
+ var name = column.name;
+ var value = record[name];
+
+ var span = $('span[name="'+name+'"]', tr);
+ span.html(value);
+
+ if (column.primary_key) {
+ // set checkbox value
+ $('input[name="select"]', tr).val(value);
+ }
+
+ if (column.primary_key && column.link) {
+ // wrap value with a link
+ var link = $('<a/>', {
+ 'click': function (value) {
+ return function() {
+ var state = {};
+ state[that.other_entity + '-facet'] = 'details';
+ state[that.other_entity + '-pkey'] = value;
+ //Before this will work, we need to set the tab one level up
+ //for example:
+ //state['identity'] = 0;
+ //but we have no way of getting the index.
+
+ $.bbq.pushState(state);
+ return false;
+ }
+ }(value)
+ });
+ span.before(link);
+ link.append(span);
+ }
+ }
+ };
+
+ that.refresh = function(container) {
+
+ function on_success(data, text_status, xhr) {
+
+ that.tbody.empty();
+
+ var column_name = that.columns[0].name;
+ var values = data.result.result[column_name];
+ //TODO, this is masking an error where the wrong
+ //direction association is presented upon page reload.
+ //if the values is unset, it is because
+ //form.associationColumns[0] doesn't exist in the results
+ if (!values) return;
+
+ for (var i = 0; i<values.length; i++){
+ var record = that.get_record(data.result.result, i);
+ that.add_row(container, record);
+ }
+ }
+
+ function on_error(xhr, text_status, error_thrown) {
+ var div = $('#'+that.id, container).empty();
+ div.append('<p>Error: '+error_thrown.name+'</p>');
+ div.append('<p>'+error_thrown.title+'</p>');
+ div.append('<p>'+error_thrown.message+'</p>');
+ }
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ ipa_cmd('show', [pkey], {}, on_success, on_error, that.entity_name);
+ };
+
+ if (spec.columns) {
+ for (var i=0; i<spec.columns; i++) {
+ that.create_column(spec.columns[i]);
+ }
+ }
+ return that;
+} \ No newline at end of file