On 02/14/2013 04:56 PM, Endi Sukma Dewata wrote:
On 2/14/2013 6:30 AM, Petr Vobornik wrote:
If they are mutually exclusive, they probably should be separated using
radio buttons like this:
PAC: ( ) None
(o) Type:
[x] MS-PAC
[ ] PAD
You missed one option: nothing selected. It can be solved by adding '(
) Inherited' radio.
I wouldn't have guessed that :) I agree we should add the 'Inherited'
option.
Anyway, this design seems more user friendly for more general audience
than mine so I will implement it. The only problem with it is that one
have to come with new label for each group and empty value - can't be
inferred from metadata.
Is there any issue adding new labels at this point? Worst case we could
hard code the label now and add a translation later.
It might be better to use a composite widget of radio buttons and
checkboxes so we can reuse the code. Probably the definition will look
something like this:
{
name: 'ipakrbauthzdata',
type: 'radio',
Not sure if it should be radio, more like something new.
Right, probably the current radio widget can't do this. So either we
improve the radio widget or create something new.
label: ...,
options: [
{
label: ...,
value: 'NONE'
},
{
label: ...,
type: 'checkboxes',
Do you expect to be there something different than checkboxes, or do you
want it to do it this way for possible future customization.
Ideally it should be generic enough to combine any widgets. This might
be a common scenario somewhere else:
Something: ( ) Option 1
( ) Option 2
(o) Other: [something else ]
This design has a flaw:
https://fedorahosted.org/freeipa/ticket/3404#comment:5
I implemented following design:
https://fedorahosted.org/freeipa/ticket/3404#comment:7
Patch attached (255-1).
I have a dilemma. I practically implemented the previous design (and
then I've found the flaw..). Patches attached as wip-fre... I wonder if
we can use it somehow or we should ditch it.
--
Petr Vobornik
From 854fb91a1fdc45f4d1ea45b9dc18f82b52a83e6d Mon Sep 17 00:00:00 2001
From: Petr Vobornik <[email protected]>
Date: Thu, 7 Mar 2013 14:16:21 +0100
Subject: [PATCH] Added Web UI support for service PAC type option: NONE
ipakrbauthzdata accepts [null, 'NONE', 'MS-PAC, 'PAD']. 'MS-PAC' and 'PAD' can be combined together but they are mutually exclusive with 'NONE'. Hence, we can't use normal radio buttons nor checkboxes.
New multivalued radio widget was developed to solve the problem. One can define option with multiple values. Thus following layout is possible:
PAC type: ( ) Inherited
( ) None
(o) MS-PAC
( ) PAD
( ) MS-PAC + PAD
https://fedorahosted.org/freeipa/ticket/3404
---
install/ui/src/freeipa/field.js | 1 +
install/ui/src/freeipa/service.js | 20 +++++++++++++++--
install/ui/src/freeipa/widget.js | 44 ++++++++++++++++++++++++++++++++++++++
install/ui/test/data/ipa_init.json | 5 +++++
ipalib/plugins/internal.py | 5 +++++
5 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/install/ui/src/freeipa/field.js b/install/ui/src/freeipa/field.js
index f705ef7b899f502b717daa384c01763c96aea664..efa9568124c0ebc59fdfc93c55a2bb888a616f90 100644
--- a/install/ui/src/freeipa/field.js
+++ b/install/ui/src/freeipa/field.js
@@ -921,6 +921,7 @@ IPA.field_factories['entity_select'] = IPA.field;
IPA.field_factories['field'] = IPA.field;
IPA.field_factories['link'] = IPA.link_field;
IPA.field_factories['multivalued'] = IPA.multivalued_field;
+IPA.field_factories['multivalued_radio'] = IPA.radio_field;
IPA.field_factories['password'] = IPA.field;
IPA.field_factories['radio'] = IPA.radio_field;
IPA.field_factories['select'] = IPA.select_field;
diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
index ecb8ce9b30518bd620dbd6ffab05342cff7a946b..8e21a9a225e2fcf5b34512c85bd471dd2cf71704 100644
--- a/install/ui/src/freeipa/service.js
+++ b/install/ui/src/freeipa/service.js
@@ -54,8 +54,24 @@ IPA.service.entity = function(spec) {
},
{
name: 'ipakrbauthzdata',
- type: 'checkboxes',
- options: IPA.create_options(['MS-PAC', 'PAD'])
+ type: 'multivalued_radio',
+ direction: 'vertical',
+ options: IPA.create_options([
+ {
+ label: IPA.messages.krbauthzdata.inherited,
+ value: ''
+ },
+ {
+ label: IPA.messages.krbauthzdata.none,
+ value: 'NONE'
+ },
+ 'MS-PAC',
+ 'PAD',
+ {
+ label: IPA.messages.krbauthzdata.mspac_pad,
+ value: 'MS-PAC,PAD'
+ }
+ ])
}
]
},
diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
index 6472cab971385d31247639c3e526c9e8f0b9063c..59e79653945d417fcc2aecddf93238082df35786 100644
--- a/install/ui/src/freeipa/widget.js
+++ b/install/ui/src/freeipa/widget.js
@@ -769,6 +769,7 @@ IPA.radio_widget = function(spec) {
that.default_value = spec.default_value;
that.options = spec.options;
+ that.direction = spec.direction || 'horizontal';
that.create = function(container) {
@@ -776,6 +777,7 @@ IPA.radio_widget = function(spec) {
container.addClass('radio-widget');
+ var vertical = that.direction === 'vertical';
var name = IPA.html_util.get_next_id(that.name+'-');
that.selector = 'input[name="'+name+'"]';
@@ -795,6 +797,10 @@ IPA.radio_widget = function(spec) {
text: option.label,
'for': id
}).appendTo(container);
+
+ if (vertical) {
+ $('<br/>').appendTo(container);
+ }
}
if (that.undo) {
@@ -846,6 +852,43 @@ IPA.radio_widget = function(spec) {
// methods that should be invoked by subclasses
that.radio_create = that.create;
that.radio_save = that.save;
+ that.radio_update = that.update;
+
+ return that;
+};
+
+/**
+ * Multivalued radio widget
+ *
+ * The difference is that it:
+ * * joins multiple values on update
+ * * splits value on save
+ *
+ * Multivalued option must be defined as ordered array joined by delimeter.
+ * Default delimeter is ','.
+ */
+IPA.multivalued_radio_widget = function(spec) {
+
+ var that = IPA.radio_widget(spec);
+ that.delimiter = spec.delimeter || ',';
+
+ that.save = function() {
+ var values = that.radio_save();
+ var rv = [];
+
+ if (values.length) {
+ rv.push.apply(rv, values[0].split(that.delimiter));
+ }
+
+ return rv;
+ };
+
+ that.update = function(values) {
+
+ var nv = [];
+ if (values && values.length) nv = [values.sort().join(that.delimiter)];
+ that.radio_update(nv);
+ };
return that;
};
@@ -3707,6 +3750,7 @@ IPA.widget_factories['header'] = IPA.header_widget;
IPA.widget_factories['html'] = IPA.html_widget;
IPA.widget_factories['link'] = IPA.link_widget;
IPA.widget_factories['multivalued'] = IPA.multivalued_widget;
+IPA.widget_factories['multivalued_radio'] = IPA.multivalued_radio_widget;
IPA.widget_factories['password'] = IPA.password_widget;
IPA.widget_factories['radio'] = IPA.radio_widget;
IPA.widget_factories['select'] = IPA.select_widget;
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 73d54578b19c53de15c237472a46312fa5e30ccc..e4554790fc8226342d466a0cc0a37143ca8cb2d5 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -131,6 +131,11 @@
"search": "Search"
},
"false": "False",
+ "krbauthzdata": {
+ "inherited": "Inherited",
+ "none": "None",
+ "mspac_pad": "MS-PAC + PAD"
+ },
"login": {
"form_auth": "To login with username and password, enter them in the fields below then click Login.",
"header": "Logged In As",
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index 2ca112ee0816a23d2b341d9a79b9447da41c506b..25ec0913bd0fcdda476dd2e6797645a340432fe4 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -266,6 +266,11 @@ class i18n_messages(Command):
"search": _("Search"),
},
"false": _("False"),
+ "krbauthzdata": {
+ "inherited": _("Inherited"),
+ "none": _("None"),
+ "mspac_pad": _("MS-PAC + PAD"),
+ },
"login": {
"form_auth": _("To login with username and password, enter them in the fields below then click Login."),
"header": _("Logged In As"),
--
1.8.1.4
From e5612e701a5048c84ddaaae02d2fdec2fccd7599 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <[email protected]>
Date: Tue, 5 Feb 2013 18:34:08 +0100
Subject: [PATCH 457/459] Added Web UI support for service PAC type option:
NONE
Checkbox for NONE option was added.
https://fedorahosted.org/freeipa/ticket/3404
---
install/ui/src/freeipa/service.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
index ecb8ce9b30518bd620dbd6ffab05342cff7a946b..703b19e5b827faf1343a0133d5f2cc426fda2d5e 100644
--- a/install/ui/src/freeipa/service.js
+++ b/install/ui/src/freeipa/service.js
@@ -55,7 +55,7 @@ IPA.service.entity = function(spec) {
{
name: 'ipakrbauthzdata',
type: 'checkboxes',
- options: IPA.create_options(['MS-PAC', 'PAD'])
+ options: IPA.create_options(['MS-PAC', 'PAD', 'NONE'])
}
]
},
@@ -465,4 +465,4 @@ IPA.service.certificate_policy = function(spec) {
IPA.register('service', IPA.service.entity);
return {};
-});
\ No newline at end of file
+});
--
1.8.1.4
From a713848bf2a6782721ff3501ece1bc6d4a7f43fe Mon Sep 17 00:00:00 2001
From: Petr Vobornik <[email protected]>
Date: Tue, 19 Feb 2013 18:02:38 +0100
Subject: [PATCH 458/459] Nesteble checkboxes-radions initial implementation
---
install/ui/ipa.css | 15 +
install/ui/src/freeipa/aci.js | 13 +-
install/ui/src/freeipa/rule.js | 3 +-
install/ui/src/freeipa/service.js | 33 ++-
install/ui/src/freeipa/widget.js | 582 ++++++++++++++++++++++++-------------
install/ui/test/data/ipa_init.json | 7 +
ipalib/plugins/internal.py | 7 +
7 files changed, 443 insertions(+), 217 deletions(-)
diff --git a/install/ui/ipa.css b/install/ui/ipa.css
index 4e51c3051e75846f386910c8998f73db7afbddaa..d43ff488f0299a109364537b636065a711a8b4a7 100644
--- a/install/ui/ipa.css
+++ b/install/ui/ipa.css
@@ -1285,6 +1285,21 @@ table.scrollable tbody {
width: 400px;
}
+.option_widget {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+.option_widget.nested {
+ padding-left: 40px;
+}
+
+.option_widget.inline,
+.option_widget.inline > li {
+ display: inline;
+}
+
.combobox-widget-input {
display: inline-block;
position: relative;
diff --git a/install/ui/src/freeipa/aci.js b/install/ui/src/freeipa/aci.js
index 383848ec635985a9582418ef4a1bb2a26dac9c36..0c8fb362fba89af155dcc08c70bdaf81336879f5 100644
--- a/install/ui/src/freeipa/aci.js
+++ b/install/ui/src/freeipa/aci.js
@@ -477,7 +477,7 @@ IPA.attributes_widget = function(spec) {
'class': 'aci-attribute-table-container'
}).appendTo(container);
- that.table = $('<table/>', {
+ that.$node = that.table = $('<table/>', {
id:id,
'class':'search-table aci-attribute-table scrollable'
}).
@@ -520,9 +520,12 @@ IPA.attributes_widget = function(spec) {
var tr = $('<tr/>').appendTo(tbody);
var td = $('<td/>').appendTo(tr);
+ var name = that.get_input_name();
+ var id = that.option_next_id + name;
td.append($('<input/>',{
+ id: id,
type: 'checkbox',
- name: that.name,
+ name: name,
value: value,
'class': 'aci-attribute',
change: function() {
@@ -531,8 +534,10 @@ IPA.attributes_widget = function(spec) {
}));
td = $('<td/>').appendTo(tr);
td.append($('<label/>',{
- text: value
+ text: value,
+ 'for': id
}));
+ that.new_option_id();
}
};
@@ -553,7 +558,7 @@ IPA.attributes_widget = function(spec) {
that.populate(that.object_type);
that.append();
- that.checkboxes_update(values);
+ that.owb_update(values);
};
that.populate = function(object_type) {
diff --git a/install/ui/src/freeipa/rule.js b/install/ui/src/freeipa/rule.js
index 888fd4508e25fc8f7913042c9da5580c73ccf623..436e934cab80c07d66f747660299e59e7a9a2ce9 100644
--- a/install/ui/src/freeipa/rule.js
+++ b/install/ui/src/freeipa/rule.js
@@ -43,7 +43,8 @@ IPA.rule_details_widget = function(spec) {
that.enable_radio.value_changed.attach(that.on_enable_radio_changed);
};
- that.on_enable_radio_changed = function(value) {
+ that.on_enable_radio_changed = function() {
+ var value = that.enable_radio.save();
if(value.length > 0) {
var enabled = ('' === value[0]);
for (var i=0; i<that.tables.length; i++) {
diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
index 703b19e5b827faf1343a0133d5f2cc426fda2d5e..0fe8db6a7278dab639c115da3fede1fbdd932f12 100644
--- a/install/ui/src/freeipa/service.js
+++ b/install/ui/src/freeipa/service.js
@@ -54,8 +54,37 @@ IPA.service.entity = function(spec) {
},
{
name: 'ipakrbauthzdata',
- type: 'checkboxes',
- options: IPA.create_options(['MS-PAC', 'PAD', 'NONE'])
+ type: 'radio',
+ layout: 'vertical',
+
+ options: [
+ {
+ label: IPA.messages.krbauthzdata.inherited,
+ value: ''
+ },
+ {
+ label: IPA.messages.krbauthzdata.none,
+ value: 'NONE'
+ },
+ {
+ label: IPA.messages.krbauthzdata.type,
+ name: 'ipakrbauthzdata_pac',
+ factory: IPA.option_widget_base,
+ input_type: 'checkbox',
+ value: 'type',
+ required: true,
+ options: [
+ {
+ label: IPA.messages.krbauthzdata.mspac,
+ value: 'MS-PAC'
+ },
+ {
+ label: IPA.messages.krbauthzdata.pad,
+ value: 'PAD'
+ }
+ ]
+ }
+ ]
}
]
},
diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
index 6472cab971385d31247639c3e526c9e8f0b9063c..ecdecd1984bd1b95f9ca036893f32ebea2b82a16 100644
--- a/install/ui/src/freeipa/widget.js
+++ b/install/ui/src/freeipa/widget.js
@@ -616,237 +616,399 @@ IPA.multivalued_widget = function(spec) {
return that;
};
+/**
+ * Widget base for checkboxes and radios. Doesn't handle dirty state's but
+ * its supposed to be nestable.
+ *
+ * Has subset of widget interface:
+ * * save(): get value
+ * * update(values): set value
+ * * value_changed: event when change happens
+ * * create_options(container): creates option part of HTML output
+ * * create: creates HTML
+ */
+IPA.option_widget_base = function(spec, that) {
+
+ spec = spec || {};
+
+
+ // when that is specified, this constructor behaves like a mixin
+ that = that || {};
+
+ /**
+ * Input name
+ * @required
+ */
+ that.name = spec.name;
+ that.label = spec.label;
+ that.tooltip = spec.tooltip;
+
+ /**
+ * Jquery reference to current node
+ */
+ that.$node = null;
+
+ /**
+ *
+ */
+ that.input_type = spec.input_type || 'checkbox';
+ that.css_class = spec.css_class || '';
+ that.value_changed = IPA.observer();
+ that.child_widgets = [];
+ that.input_name = null;
+ that.selector = null;
+ that.option_next_id = 0;
+ that.nested = !!spec.nested;
+ that.default_value = spec.default_value || null;
+ that.unselect_childs = spec.unselect_childs === undefined ? true : !!spec.unselect_childs;
+
+ /**
+ * How items should be rendered.
+ * * inline
+ * * vertical
+ */
+ that.layout = spec.layout || 'vertical';
+
+
+ that.prepare_options = function(options) {
+
+ var ret = [];
+
+ if (!options) return options;
+
+ for (var i=0; i<options.length; i++) {
+ ret.push(that.prepare_option(options[i]));
+ }
+
+ return ret;
+ };
+
+ that.prepare_option = function(option) {
+
+ var ret = option;
+
+ if (!option) throw {
+ error: 'Invalid option specified',
+ option: option
+ };
+
+ if (typeof option === 'string') {
+ ret = {
+ label: option,
+ value: option
+ };
+ }
+
+ return ret;
+ };
+
+ that.add_option = function(option, suppress_update) {
+ that.options.push(that.prepare_option(option));
+ if (!suppress_update) that.update_dom();
+ };
+
+ that.update_dom = function() {
+
+ if (that.$node) {
+ var values = that.save();
+ var container = that.$node.parent();
+ that.create(container);
+ that.update(values);
+ }
+ };
+
+ that.create_options = function(container) {
+ for (var i=0; i<that.options.length; i++) {
+ var option_container = that.create_option_container();
+ var option = that.options[i];
+ that.create_option(option, option_container);
+ option_container.appendTo(container);
+ }
+ };
+
+ that.create_option_container = function() {
+ return $('<li/>');
+ };
+
+ that._create_option = function(option, container) {
+ var input_name = that.get_input_name();
+ var id = that.option_next_id + input_name;
+
+ $('<input/>', {
+ id: id,
+ type: that.input_type,
+ name: input_name,
+ value: option.value,
+ title: option.tooltip || that.tooltip,
+ change: that.on_input_change
+ }).appendTo(container);
+
+ $('<label/>', {
+ text: option.label,
+ title: option.tooltip || that.tooltip,
+ 'for': id
+ }).appendTo(container);
+
+ that.new_option_id();
+ };
+
+ that.create_option = function(option, container) {
+
+ if (option.type || option.factory) {
+
+ that._create_option(option, container);
+
+ var factory = option.factory || IPA.widget_factories[option.type];
+
+ if (typeof factory !== 'function') throw {
+ error: 'Invalid factory',
+ factory: factory
+ };
+ option.nested = true;
+ option.widget = factory(option);
+ option.widget.value_changed.attach(that.on_input_change);
+ option.widget.create(container);
+ that.child_widgets.push(option.widget);
+ } else {
+ that._create_option(option, container);
+ }
+ };
+
+ that.new_option_id = function() {
+ that.option_next_id++;
+ };
+
+ that.get_input_name = function() {
+
+ if (!that.input_name) {
+ var name = that.name;
+ if (that.input_type === 'radio') {
+ name = IPA.html_util.get_next_id(name);
+ }
+ that.input_name = name;
+ that.selector = 'input[name="'+name+'"]';
+ }
+ return that.input_name;
+ };
+
+ that.create = function(container) {
+ that.destroy();
+ that.create_options(that.$node);
+ var css_class = [that.css_class, 'option_widget', that.layout,
+ that.nested ? 'nested': ''].join(' ');
+
+ that.$node = $('<ul/>', { 'class': css_class });
+ that.create_options(that.$node);
+
+ if (container) that.$node.appendTo(container);
+ };
+
+ that.destroy = function() {
+ if (that.$node) {
+ that.$node.empty();
+ that.$node.remove();
+ }
+
+ var widget = that.child_widgets.pop();
+ while (widget) {
+ widget.value_changed.detach(that.on_input_change);
+ widget.destroy();
+ widget = that.child_widgets.pop();
+ }
+ };
+
+ that.get_option = function(value) {
+ for (var i=0; i<that.options.length; i++) {
+ var option = that.options[i];
+ if (option.value === value) return option;
+ }
+ return null;
+ };
+
+ that.on_input_change = function(e) {
+
+ // clear child widgets on deselect of parent options
+ if (that.child_widgets.length > 0 && that.unselect_childs) {
+
+ var parents_selected = [];
+
+ $(that.selector+':checked', that.container).each(function() {
+ var value = $(this).val();
+ var option = that.get_option(value);
+ if (option && option.nested) {
+ parents_selected.push(value);
+ }
+ });
+
+ for (var i=0; i<that.options.length; i++) {
+
+ var option = that.options[i];
+
+ if (option.nested) {
+ var selected = parents_selected.indexOf(option.value) > -1;
+ option.widget.set_enabled(selected);
+ }
+ }
+ }
+ that.value_changed.notify([], that);
+ };
+
+ that.save = function() {
+
+ var values = [];
+
+ if (that.$node) {
+
+ $(that.selector+':checked', that.container).each(function() {
+ var value = $(this).val();
+ var option = that.get_option(value);
+
+ // don't include if it has nested options
+ if (!option || !option.nested || option.include_nested) {
+ values.push(value);
+ }
+ });
+
+ for (var i=0; i<that.child_widgets.length; i++) {
+ var child = that.child_widgets[i];
+ var child_values = child.save() || [];
+ if (child_values.length > 0) {
+ values.push.apply(values, child_values);
+ }
+ }
+ }
+
+ return values;
+ };
+
+ that.update = function(values) {
+
+ var check = function(selector, uncheck) {
+ $(selector, that.$node).prop('checked', !uncheck);
+ };
+
+ if (that.$node) {
+
+ // deselect all inputs
+ check(that.selector, true /*uncheck*/);
+
+ if (values && values.length > 0) {
+ // try to select inputs with matching value
+ for (var i=0; i<values.length; i++) {
+ var value = values[i];
+ check(that.selector+'[value="'+value+'"]');
+ }
+ } else {
+ // select default if none specified
+ if (that.default_value !== null) {
+ check(that.selector+'[value="'+that.default_value+'"]');
+ } else {
+ // otherwise select empty
+ check(that.selector+'[value=""]');
+ }
+ }
+
+ for (var j=0; j<that.child_widgets.length; j++) {
+ that.child_widgets[j].update(values);
+ }
+ }
+ };
+
+ that.set_enabled = function(enabled) {
+
+ $(that.selector, that.container).prop('disabled', !enabled);
+ if (!enabled) that.clear();
+ for (var i=0; i<that.child_widgets.length;i++){
+ that.child_widgets[i].set_enabled(enabled);
+ }
+ };
+
+
+ that.clear = function() {
+
+ $(that.selector, that.$node).prop('checked', false);
+
+ if (that.default_value) {
+ $(that.selector+'[value="'+that.default_value+'"]', that.$node).
+ prop('checked', true);
+ }
+
+ for (var i=0; i<that.child_widgets.length; i++) {
+ that.child_widgets[i].clear();
+ }
+ };
+
+ that.options = that.prepare_options(spec.options || []);
+
+ that.owb_create = that.create;
+ that.owb_save = that.save;
+ that.owb_update = that.update;
+
+ return that;
+};
+
+IPA.radio_widget = function(spec) {
+
+ spec = spec || {};
+ spec.input_type = spec.input_type || 'radio';
+ spec.layout = spec.layout || 'inline';
+
+ var that = IPA.input_widget(spec);
+ IPA.option_widget_base(spec, that);
+
+ that.create = function(container) {
+ that.widget_create(container);
+ that.owb_create(container);
+ container.addClass('radio-widget');
+
+ if (that.undo) {
+ that.create_undo(container);
+ }
+
+ that.create_error_link(container);
+ };
+ return that;
+};
+
IPA.checkbox_widget = function (spec) {
+ var checked = 'checked';
+
spec = spec || {};
+ spec.input_type = spec.input_type || 'checkbox';
- var that = IPA.input_widget(spec);
+ if (!spec.options) {
+ spec.options = [ { value: checked, label: '' } ];
+ }
- // default value
- that.checked = spec.checked || false;
+ if (spec.checked) spec.default_value = spec.checked;
- that.create = function(container) {
-
- that.widget_create(container);
-
- container.addClass('checkbox-widget');
-
- that.input = $('<input/>', {
- type: 'checkbox',
- name: that.name,
- checked: that.checked,
- title: that.tooltip,
- change: function() {
- that.value_changed.notify([that.save()], that);
- }
- }).appendTo(container);
-
- if (that.undo) {
- that.create_undo(container);
- }
-
- that.create_error_link(container);
- };
+ var that = IPA.radio_widget(spec);
that.save = function() {
- var value = that.input.is(':checked');
- return [value];
+ var values = that.owb_save();
+ return [values.length > 0];
};
that.update = function(values) {
- var value;
-
- if (values && values.length) {
- value = values[0];
- }
+ var value = values ? values[0] : '';
if (typeof value !== 'boolean') {
- // use default value
- value = that.checked;
+ value = that.default_value || '';
+ } else {
+ value = value ? checked : '';
}
-
- that.input.prop('checked', value);
+ that.owb_update([value]);
};
- that.clear = function() {
- that.input.prop('checked', false);
- };
-
- that.checkbox_save = that.save;
-
return that;
};
IPA.checkboxes_widget = function (spec) {
-
spec = spec || {};
-
- var that = IPA.input_widget(spec);
-
- that.options = spec.options || [];
- that.direction = spec.direction || 'vertical';
-
- that.create = function(container) {
-
- that.widget_create(container);
-
- container.addClass('checkboxes-widget');
-
- var vertical = that.direction === 'vertical';
-
- for (var i=0; i<that.options.length; i++) {
- var option = that.options[i];
- $('<input/>', {
- type: 'checkbox',
- name: that.name,
- value: option.value,
- title: that.tooltip
- }).appendTo(container);
-
- $('<label/>', {
- text: option.label,
- title: that.tooltip
- }).appendTo(container);
-
- if (vertical) {
- $('<br/>').appendTo(container);
- }
- }
-
- if (that.undo) {
- that.create_undo(container);
- }
-
- var input = $('input[name="'+that.name+'"]', that.container);
- input.change(function() {
- that.value_changed.notify([that.save()], that);
- });
-
- that.create_error_link(container);
- };
-
- that.save = function() {
- var values = [];
-
- $('input[name="'+that.name+'"]:checked', that.container).each(function() {
- values.push($(this).val());
- });
-
- return values;
- };
-
- that.update = function(values) {
- var inputs = $('input[name="'+that.name+'"]', that.container);
- inputs.prop('checked', false);
-
- for (var j=0; values && j<values.length; j++) {
- var value = values[j];
- var input = $('input[name="'+that.name+'"][value="'+value+'"]', that.container);
- if (!input.length) continue;
- input.prop('checked', true);
- }
- };
-
- that.clear = function() {
- $('input[name="'+that.name+'"]').prop('checked', false);
- };
-
- that.add_option = function(option) {
- that.options.push(option);
- };
-
- // methods that should be invoked by subclasses
- that.checkboxes_update = that.update;
-
- return that;
-};
-
-IPA.radio_widget = function(spec) {
-
- spec = spec || {};
-
- var that = IPA.input_widget(spec);
-
- that.default_value = spec.default_value;
- that.options = spec.options;
-
- that.create = function(container) {
-
- that.widget_create(container);
-
- container.addClass('radio-widget');
-
- var name = IPA.html_util.get_next_id(that.name+'-');
- that.selector = 'input[name="'+name+'"]';
-
- for (var i=0; i<that.options.length; i++) {
- var option = that.options[i];
-
- var id = name+'-'+i;
-
- $('<input/>', {
- id: id,
- type: 'radio',
- name: name,
- value: option.value
- }).appendTo(container);
-
- $('<label/>', {
- text: option.label,
- 'for': id
- }).appendTo(container);
- }
-
- if (that.undo) {
- that.create_undo(container);
- }
-
- var input = $(that.selector, that.container);
- input.change(function() {
- that.value_changed.notify([that.save()], that);
- });
-
- that.create_error_link(container);
- };
-
- that.save = function() {
- var input = $(that.selector+':checked', that.container);
- if (!input.length) return [];
- return [input.val()];
- };
-
- that.update = function(values) {
-
- $(that.selector, that.container).each(function() {
- var input = this;
- input.checked = false;
- });
-
- var value = values && values.length ? values[0] : '';
- var input = $(that.selector+'[value="'+value+'"]', that.container);
- if (input.length) {
- input.prop('checked', true);
- } else if (that.default_value) {
- input = $(that.selector+'[value="'+that.default_value+'"]', that.container);
- input.prop('checked', true);
- }
-
- that.value_changed.notify([that.save()], that);
- };
-
- that.clear = function() {
- $(that.selector, that.container).prop('checked', false);
-
- if (that.default_value) {
- var input = $(that.selector+'[value="'+that.default_value+'"]', that.container);
- input.prop('checked', true);
- }
- };
-
- // methods that should be invoked by subclasses
- that.radio_create = that.create;
- that.radio_save = that.save;
-
+ spec.input_type = spec.input_type || 'checkbox';
+ spec.layout = spec.layout || 'vertical';
+ var that = IPA.radio_widget(spec);
return that;
};
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 73d54578b19c53de15c237472a46312fa5e30ccc..e03dd077b9047e25e44c32c2ad67c7a07a6c910e 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -131,6 +131,13 @@
"search": "Search"
},
"false": "False",
+ "krbauthzdata": {
+ "inherited": "Inherited",
+ "mspac": "MS-PAC",
+ "none": "None",
+ "pad": "PAD",
+ "type": "Type"
+ },
"login": {
"form_auth": "To login with username and password, enter them in the fields below then click Login.",
"header": "Logged In As",
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index 2ca112ee0816a23d2b341d9a79b9447da41c506b..a60fa271004bdda6defdd0bd107c9060a4a8fcf1 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -266,6 +266,13 @@ class i18n_messages(Command):
"search": _("Search"),
},
"false": _("False"),
+ "krbauthzdata": {
+ "inherited": _("Inherited"),
+ "mspac": _("MS-PAC"),
+ "none": _("None"),
+ "pad": _("PAD"),
+ "type": _("Type"),
+ },
"login": {
"form_auth": _("To login with username and password, enter them in the fields below then click Login."),
"header": _("Logged In As"),
--
1.8.1.4
From 3b4a716e68bf0f36fc5efad28f287061cd99455b Mon Sep 17 00:00:00 2001
From: Petr Vobornik <[email protected]>
Date: Wed, 6 Mar 2013 18:50:23 +0100
Subject: [PATCH 459/459] Multivalued widget
---
install/ui/src/freeipa/field.js | 1 +
install/ui/src/freeipa/service.js | 28 +++++++++++-----------------
install/ui/src/freeipa/widget.js | 38 ++++++++++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+), 17 deletions(-)
diff --git a/install/ui/src/freeipa/field.js b/install/ui/src/freeipa/field.js
index f705ef7b899f502b717daa384c01763c96aea664..ce621c06ad85a91341f111948eb6ea04174ccc8e 100644
--- a/install/ui/src/freeipa/field.js
+++ b/install/ui/src/freeipa/field.js
@@ -921,6 +921,7 @@ IPA.field_factories['entity_select'] = IPA.field;
IPA.field_factories['field'] = IPA.field;
IPA.field_factories['link'] = IPA.link_field;
IPA.field_factories['multivalued'] = IPA.multivalued_field;
+IPA.field_factories['multivalued_radio'] = IPA.field;
IPA.field_factories['password'] = IPA.field;
IPA.field_factories['radio'] = IPA.radio_field;
IPA.field_factories['select'] = IPA.select_field;
diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
index 0fe8db6a7278dab639c115da3fede1fbdd932f12..0528072ca63eb993781e4eda3bdc5741c250196d 100644
--- a/install/ui/src/freeipa/service.js
+++ b/install/ui/src/freeipa/service.js
@@ -54,7 +54,7 @@ IPA.service.entity = function(spec) {
},
{
name: 'ipakrbauthzdata',
- type: 'radio',
+ type: 'multivalued_radio',
layout: 'vertical',
options: [
@@ -67,22 +67,16 @@ IPA.service.entity = function(spec) {
value: 'NONE'
},
{
- label: IPA.messages.krbauthzdata.type,
- name: 'ipakrbauthzdata_pac',
- factory: IPA.option_widget_base,
- input_type: 'checkbox',
- value: 'type',
- required: true,
- options: [
- {
- label: IPA.messages.krbauthzdata.mspac,
- value: 'MS-PAC'
- },
- {
- label: IPA.messages.krbauthzdata.pad,
- value: 'PAD'
- }
- ]
+ label: IPA.messages.krbauthzdata.mspac,
+ value: 'MS-PAC'
+ },
+ {
+ label: IPA.messages.krbauthzdata.pad,
+ value: 'PAD'
+ },
+ {
+ label: 'MS-PAC + PAD',
+ value: 'MS-PAC,PAD'
}
]
}
diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
index ecdecd1984bd1b95f9ca036893f32ebea2b82a16..f39659f260f216376b38ccbe09bbe0621a79ee24 100644
--- a/install/ui/src/freeipa/widget.js
+++ b/install/ui/src/freeipa/widget.js
@@ -970,6 +970,43 @@ IPA.radio_widget = function(spec) {
return that;
};
+
+/**
+ * Multivalued radio widget
+ *
+ * The difference is that it:
+ * * joins multiple values on update
+ * * splits value on save
+ *
+ * Multivalued option must be defined as ordered array joined by delimeter.
+ * Default delimeter is ','.
+ */
+IPA.multivalued_radio_widget = function(spec) {
+
+ var that = IPA.radio_widget(spec);
+ that.delimiter = spec.delimeter || ',';
+
+ that.save = function() {
+ var values = that.owb_save();
+ var rv = [];
+
+ for (var i=0; i<values.length; i++) {
+ rv.push.apply(rv, values[i].split(that.delimiter));
+ }
+
+ return rv;
+ };
+
+ that.update = function(values) {
+
+ var nv = [];
+ if (values.length) nv = [values.sort().join(that.delimiter)];
+ that.owb_update(nv);
+ };
+
+ return that;
+};
+
IPA.checkbox_widget = function (spec) {
var checked = 'checked';
@@ -3869,6 +3906,7 @@ IPA.widget_factories['header'] = IPA.header_widget;
IPA.widget_factories['html'] = IPA.html_widget;
IPA.widget_factories['link'] = IPA.link_widget;
IPA.widget_factories['multivalued'] = IPA.multivalued_widget;
+IPA.widget_factories['multivalued_radio'] = IPA.multivalued_radio_widget;
IPA.widget_factories['password'] = IPA.password_widget;
IPA.widget_factories['radio'] = IPA.radio_widget;
IPA.widget_factories['select'] = IPA.select_widget;
--
1.8.1.4
_______________________________________________
Freeipa-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/freeipa-devel