summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--install/ui/facet.js370
-rw-r--r--install/ui/ipa.css55
-rw-r--r--install/ui/ipa.js4
-rw-r--r--install/ui/test/data/ipa_init.json6
-rw-r--r--install/ui/widget.js104
-rw-r--r--ipalib/plugins/internal.py6
6 files changed, 527 insertions, 18 deletions
diff --git a/install/ui/facet.js b/install/ui/facet.js
index 01e8a935..5e78d57f 100644
--- a/install/ui/facet.js
+++ b/install/ui/facet.js
@@ -42,6 +42,7 @@ IPA.facet = function(spec) {
that.disable_breadcrumb = spec.disable_breadcrumb;
that.disable_facet_tabs = spec.disable_facet_tabs;
+ that.action_list = spec.action_list;
that.header = spec.header || IPA.facet_header({ facet: that });
that._needs_update = spec.needs_update;
@@ -309,6 +310,23 @@ IPA.facet_header = function(spec) {
that.facet = spec.facet;
+ var init = function() {
+
+ if (that.facet.action_list) {
+
+ var widget_builder = IPA.widget_builder({
+ widget_options: {
+ entity: that.facet.entity
+ }
+ });
+
+ that.action_list = widget_builder.build_widget(that.facet.action_list);
+ that.action_list.init();
+ }
+
+ that.title_widget = IPA.facet_title();
+ };
+
that.select_tab = function() {
if (that.facet.disable_facet_tabs) return;
@@ -372,16 +390,14 @@ IPA.facet_header = function(spec) {
}).appendTo(that.path);
}
- that.title_container.empty();
- var h3 = $('<h3/>').appendTo(that.title_container);
- h3.append(that.facet.label);
- h3.append(': ');
+ var title_info = {
+ title: that.facet.label,
+ pkey: limited_value,
+ pkey_tooltip: value
+ };
+ that.title_widget.update(title_info);
- $('<span/>', {
- 'class': 'facet-pkey',
- title: value,
- text: limited_value
- }).appendTo(h3);
+ that.adjust_elements();
};
that.create_facet_link = function(container, other_facet) {
@@ -431,6 +447,8 @@ IPA.facet_header = function(spec) {
that.create = function(container) {
+ that.container = container;
+
if (!that.facet.disable_breadcrumb) {
that.breadcrumb = $('<div/>', {
'class': 'breadcrumb'
@@ -456,13 +474,16 @@ IPA.facet_header = function(spec) {
}).appendTo(that.breadcrumb);
}
- that.title_container = $('<div/>', {
- 'class': 'facet-title'
- }).appendTo(container);
+ that.title_widget.create(container);
+ that.title_widget.update({ title: that.facet.label });
- var span = $('<h3/>', {
- text: that.facet.label
- }).appendTo(that.title_container);
+ if (that.action_list) {
+ that.action_list_container = $('<div/>', {
+ 'class': 'facet-action-list'
+ }).appendTo(container);
+
+ that.action_list.create(that.action_list_container);
+ }
if (!that.facet.disable_facet_tabs) {
that.facet_tabs = $('<div/>', {
@@ -518,12 +539,112 @@ IPA.facet_header = function(spec) {
}
}
}
+
+ if (that.action_list) {
+ that.action_list.update(result);
+
+ var state = that.action_list.state;
+ var icon_tooltip = that.action_list.state_evaluator.get_description();
+ if (state.length > 0) {
+ var css_class = state.join(' ');
+ that.title_widget.set_class(css_class);
+ that.title_widget.set_icon_tooltip(icon_tooltip);
+ }
+ }
+
+ that.adjust_elements();
+ };
+
+ that.adjust_elements = function() {
+
+ if (that.action_list) {
+
+ var action_list = that.action_list.container;
+ var max_width = that.container.width();
+ var al_width = action_list.width();
+ var title_width = that.title_widget.title_container.width();
+ var title_max = max_width - al_width;
+
+ that.title_widget.set_max_width(title_max);
+ action_list.css('left', title_width + 'px');
+ }
};
that.clear = function() {
that.load();
};
+ init();
+
+ return that;
+};
+
+IPA.facet_title = function(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.update = function(data) {
+
+ var tooltip = data.tooltip || data.title;
+ var pkey_tooltip = data.pkey_tooltip || data.pkey;
+ var icon_tooltip = data.icon_tooltip || '';
+
+ that.title.text(data.title);
+ that.title.attr('title', tooltip);
+
+ if (data.pkey) {
+ that.title.text(data.title + ': ');
+ that.pkey.text(data.pkey);
+ that.pkey.attr('title', pkey_tooltip);
+ }
+
+ if (data.css_class) that.set_class(data.css_class);
+
+ that.set_icon_tooltip(icon_tooltip);
+ };
+
+ that.create = function(container) {
+
+ that.title_container = $('<div/>', {
+ 'class': 'facet-title'
+ }).appendTo(container);
+
+ that.icon = $('<div />', {
+ 'class': 'header-icon'
+ }).appendTo(that.title_container);
+
+ var h3 = $('<h3/>').appendTo(that.title_container);
+
+ that.title = $('<span/>').appendTo(h3);
+
+ that.pkey = $('<span/>', {
+ 'class': 'facet-pkey'
+ }).appendTo(h3);
+ };
+
+ that.set_max_width = function(width) {
+ that.title_container.css('max-width', width+'px');
+ };
+
+ that.set_class = function(css_class) {
+
+ if (that.css_class) {
+ that.title_container.removeClass(that.css_class);
+ }
+
+ if (css_class) {
+ that.title_container.addClass(css_class);
+ }
+
+ that.css_class = css_class;
+ };
+
+ that.set_icon_tooltip = function(tooltip) {
+ that.icon.attr('title', tooltip);
+ };
+
return that;
};
@@ -1025,7 +1146,7 @@ IPA.facet_builder = function(entity) {
(IPA.metadata.objects[spec.other_entity] ?
IPA.metadata.objects[spec.other_entity].label : spec.other_entity);
- if(that.has_indirect_attribute_member(spec)) {
+ if (that.has_indirect_attribute_member(spec)) {
spec.indirect_attribute_member = spec.attribute_member + 'indirect';
}
@@ -1042,8 +1163,8 @@ IPA.facet_builder = function(entity) {
that.has_indirect_attribute_member = function(spec) {
var indirect_members = entity.metadata.attribute_members[spec.attribute_member + 'indirect'];
- if(indirect_members) {
- if(indirect_members.indexOf(spec.other_entity) > -1) {
+ if (indirect_members) {
+ if (indirect_members.indexOf(spec.other_entity) > -1) {
return true;
}
}
@@ -1054,3 +1175,216 @@ IPA.facet_builder = function(entity) {
return that;
};
+
+IPA.action = function(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.name = spec.name;
+ that.label = spec.label;
+ that.enable_cond = spec.enable_cond || [];
+ that.disable_cond = spec.disable_cond || [];
+ that.handler = spec.handler;
+ that.needs_confirm = spec.needs_confirm !== undefined ? spec.needs_confirm : true;
+ that.confirm_msg = spec.confirm_msg || IPA.messages.actions.confirm;
+
+ that.execute = function(facet, on_success, on_error) {
+
+ if (that.handler) {
+ that.handler(facet, on_success, on_error);
+ }
+ };
+
+ return that;
+};
+
+IPA.action_builder = function(spec) {
+
+ spec = spec || {};
+ spec.factory = spec.factory || IPA.action;
+ var that = IPA.builder(spec);
+ return that;
+};
+
+IPA.state_evaluator = function(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.evaluate = function() {
+ that.state = [];
+ return that.state;
+ };
+
+ that.get_description = function() {
+ return that.description || '';
+ };
+
+ return that;
+};
+
+
+IPA.action_list_widget = function(spec) {
+
+ spec = spec || {};
+
+ spec.widgets = spec.widgets || [
+ {
+ type: 'html',
+ css_class: 'separator'
+ },
+ {
+ type: 'select',
+ name: 'action',
+ undo: false
+ },
+ {
+ type: 'button',
+ name: 'apply',
+ label: "Apply" //TODO: translate
+ }
+ ];
+
+ var that = IPA.composite_widget(spec);
+
+ that.actions = IPA.build(spec.actions, IPA.action_builder) || [];
+ that.state_evaluator = IPA.build(spec.state_evaluator);
+ that.state = [];
+
+ that.init = function() {
+ that.action_select = that.widgets.get_widget('action');
+ that.apply_button = that.widgets.get_widget('apply');
+
+ that.action_select.value_changed.attach(that.on_action_change);
+ that.apply_button.click = that.on_apply;
+
+ var options = [];
+
+ for (var i=0; i< that.actions.length; i++) {
+ var action = that.actions[i];
+ options.push({
+ label: action.label,
+ value: action.name
+ });
+ }
+
+ that.action_select.options = options;
+ };
+
+ that.on_action_change = function() {
+
+ var selected = that.action_select.save()[0];
+ var action = that.get_action(selected);
+ var enabled = that.action_enabled(action);
+ that.apply_button.set_enabled(enabled);
+ };
+
+ that.on_apply = function() {
+ var selected = that.action_select.save()[0];
+ var action = that.get_action(selected);
+ var enabled = that.action_enabled(action);
+ var facet = that.entity.get_facet();
+
+ if (enabled) {
+ action.execute(facet,
+ that.on_action_success,
+ that.on_action_error);
+ }
+ };
+
+ that.on_action_success = function() {
+ var facet = that.entity.get_facet();
+ facet.refresh();
+ };
+
+ that.on_action_error = function() {
+ var facet = that.entity.get_facet();
+ facet.refresh();
+ };
+
+ that.update = function(result) {
+
+ that.get_state(result);
+ var disabled = that.get_disabled();
+ that.action_select.enable_options();
+ that.action_select.disable_options(disabled);
+ that.select_first_enabled();
+ };
+
+ that.get_state = function(result) {
+
+ if (that.state_evaluator) {
+ that.state = that.state_evaluator.evaluate(result);
+ }
+ };
+
+ that.get_action = function(name) {
+
+ for (var i=0; i< that.actions.length; i++) {
+ var action = that.actions[i];
+ if (action.name === name) {
+ return action;
+ }
+ }
+ return null;
+ };
+
+ that.get_disabled = function() {
+
+ var disabled = [];
+
+ for (var i=0; i< that.actions.length; i++) {
+ var action = that.actions[i];
+ if (!that.action_enabled(action)) {
+ disabled.push(action.name);
+ }
+ }
+
+ return disabled;
+ };
+
+ that.action_enabled = function(action) {
+
+ var i, cond;
+
+ if (action.disable_cond) {
+ for (i=0; i<action.disable_cond.length; i++) {
+ cond = action.disable_cond[i];
+ if (that.state.indexOf(cond) > -1) {
+ return false;
+ }
+ }
+ }
+
+ if (action.enable_cond) {
+ for (i=0; i<action.enable_cond.length; i++) {
+ cond = action.enable_cond[i];
+ if (that.state.indexOf(cond) < 0) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+ that.select_first_enabled = function() {
+
+ var first = that.actions[0].name;
+
+ for (var i=0; i< that.actions.length; i++) {
+ var action = that.actions[i];
+ if (that.action_enabled(action)) {
+ first = action.name;
+ break;
+ }
+ }
+
+ that.action_select.update([first]);
+ };
+
+ return that;
+}; \ No newline at end of file
diff --git a/install/ui/ipa.css b/install/ui/ipa.css
index 7e795660..d83c7e14 100644
--- a/install/ui/ipa.css
+++ b/install/ui/ipa.css
@@ -1052,6 +1052,11 @@ span.main-separator{
cursor: default;
}
+.button-disabled {
+ color: gray;
+ cursor: default;
+}
+
.aci-attribute-table tbody {
border-bottom: 1px solid #8a8a8a;
height:10em;
@@ -1637,3 +1642,53 @@ form#login {
.auth-dialog h3 {
margin: 0.5em;
}
+
+/* --- Action list --- */
+
+.facet-action-list {
+ position: absolute;
+ left: 200px;
+ top: 15px;
+ height: 24px;
+ vertical-align: top;
+}
+
+.facet-action-list div {
+ display: inline-block;
+ vertical-align: top;
+}
+
+.facet-action-list div[name=apply] {
+ margin-left: 10px;
+}
+
+ #content .facet-action-list div[name=apply] a.ui-state-default {
+ padding: 3px 5px 1px 5px;
+}
+
+.facet-action-list select {
+ font-size: 11px;
+ padding-left: 4px;
+ padding-right: 4px;
+ height: 24px;
+}
+
+.facet-action-list .separator {
+ width: 1px;
+ height: 24px;
+ margin-left: 10px;
+ margin-right: 15px;
+ background-color: #a1a1a1;
+}
+
+/* --- Facet title states --- */
+
+.facet-title h3 {
+ display: inline-block;
+}
+
+.facet-title .header-icon {
+ display: none;
+ width: 17px;
+ height: 17px;
+}
diff --git a/install/ui/ipa.js b/install/ui/ipa.js
index 4470d948..648fcfc3 100644
--- a/install/ui/ipa.js
+++ b/install/ui/ipa.js
@@ -1657,6 +1657,10 @@ IPA.array_diff = function(a, b) {
return false;
};
+IPA.confirm = function(msg) {
+ return window.confirm(msg);
+};
+
IPA.config = {
default_priority: 500
};
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 7d394f8a..333cb19a 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -13,6 +13,12 @@
"title": "Kerberos ticket no longer valid."
}
},
+ "actions": {
+ "confirm": "Are you sure you want to proceed with the action.",
+ "delete_confirm": "Are you sure you want to delete ${object}",
+ "disable_confirm": "Are you sure you want to disable ${object}",
+ "enable_confirm": "Are you sure you want to enable ${object}"
+ },
"association": {
"add": {
"ipasudorunas": "Add RunAs ${other_entity} into ${entity} ${primary_key}",
diff --git a/install/ui/widget.js b/install/ui/widget.js
index ff775974..d3efe499 100644
--- a/install/ui/widget.js
+++ b/install/ui/widget.js
@@ -891,6 +891,19 @@ IPA.select_widget = function(spec) {
$('option', that.select).attr('selected', '');
};
+ that.enable_options = function() {
+ $('option', that.select).attr('disabled', '');
+ };
+
+ that.disable_options = function(options) {
+
+ for (var i=0; i<options.length;i++) {
+ var value = options[i];
+ var option = $('option[value="'+value+'"]', that.select);
+ option.attr('disabled', 'disabled');
+ }
+ };
+
// methods that should be invoked by subclasses
that.select_save = that.save;
that.select_update = that.update;
@@ -2432,6 +2445,95 @@ IPA.button = function(spec) {
return button;
};
+IPA.button_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.href = spec.href;
+ that.style = spec.style;
+ that.click = spec.click;
+ that['class'] = spec['class'];
+ that.disabled_class = 'button-disabled';
+
+ that.on_click = function() {
+
+ if (that.click) {
+ that.click();
+ }
+ return false;
+ };
+
+ that.create = function(container) {
+ that.button = IPA.button({
+ id: that.id,
+ name: that.name,
+ href: that.href,
+ title: that.tooltip,
+ label: that.label,
+ 'class': that['class'],
+ style: that.style,
+ click: that.on_click
+ }).appendTo(container);
+ };
+
+ that.get_enabled = function() {
+
+ var enabled = true;
+
+ if (that.button) {
+ enabled = that.button.hasClass(that.disabled_class);
+ }
+
+ return enabled;
+ };
+
+ that.set_enabled = function(enabled) {
+
+ enabled ? that.enable() : that.disable();
+ };
+
+ that.enable = function() {
+ if (that.button) {
+ that.button.removeClass(that.disabled_class);
+ }
+ };
+
+ that.disable = function() {
+ if (that.button) {
+ that.button.addClass(that.disabled_class);
+ }
+ };
+
+ return that;
+};
+
+IPA.html_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.html = spec.html;
+ that.css_class = spec.css_class;
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ if (that.css_class) {
+ container.addClass(that.css_class);
+ }
+
+ if (that.html) {
+ container.append(that.html);
+ }
+ };
+
+ return that;
+};
+
IPA.composite_widget = function(spec) {
spec = spec || {};
@@ -3016,6 +3118,7 @@ IPA.sshkey_widget = function(spec) {
IPA.widget_factories['attribute_table'] = IPA.attribute_table_widget;
+IPA.widget_factories['button'] = IPA.button_widget;
IPA.widget_factories['checkbox'] = IPA.checkbox_widget;
IPA.widget_factories['checkboxes'] = IPA.checkboxes_widget;
IPA.widget_factories['combobox'] = IPA.combobox_widget;
@@ -3025,6 +3128,7 @@ IPA.widget_factories['details_table_section_nc'] = IPA.details_table_section_nc;
IPA.widget_factories['enable'] = IPA.enable_widget;
IPA.widget_factories['entity_select'] = IPA.entity_select_widget;
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['password'] = IPA.password_widget;
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index 66507c88..e7fb6651 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -148,6 +148,12 @@ class i18n_messages(Command):
"title": _("Kerberos ticket no longer valid."),
},
},
+ "actions": {
+ "confirm": _("Are you sure you want to proceed with the action."),
+ "delete_confirm": _("Are you sure you want to delete ${object}"),
+ "disable_confirm": _("Are you sure you want to disable ${object}"),
+ "enable_confirm": _("Are you sure you want to enable ${object}"),
+ },
"association": {
"add": {
"ipasudorunas": _("Add RunAs ${other_entity} into ${entity} ${primary_key}"),