diff options
author | Petr Vobornik <pvoborni@redhat.com> | 2014-04-14 14:10:20 +0200 |
---|---|---|
committer | Petr Vobornik <pvoborni@redhat.com> | 2014-06-10 10:23:25 +0200 |
commit | c7af2458091ba95eccc26f4468234413e8b016b9 (patch) | |
tree | 4ced522bf92ac2c38a9726a0c441c713d63068cb /install | |
parent | fc0926ba91f57cb5cd182f2edf50f24d4cfd7432 (diff) | |
download | freeipa-c7af2458091ba95eccc26f4468234413e8b016b9.tar.gz freeipa-c7af2458091ba95eccc26f4468234413e8b016b9.tar.xz freeipa-c7af2458091ba95eccc26f4468234413e8b016b9.zip |
webui: add action dropdown
Reviewed-By: Endi Sukma Dewata <edewata@redhat.com>
Diffstat (limited to 'install')
-rw-r--r-- | install/ui/ipa.css | 20 | ||||
-rw-r--r-- | install/ui/src/freeipa/details.js | 1 | ||||
-rw-r--r-- | install/ui/src/freeipa/facet.js | 34 | ||||
-rw-r--r-- | install/ui/src/freeipa/search.js | 1 | ||||
-rw-r--r-- | install/ui/src/freeipa/widgets/ActionDropdownWidget.js | 191 | ||||
-rw-r--r-- | install/ui/src/freeipa/widgets/DropdownWidget.js | 84 |
6 files changed, 310 insertions, 21 deletions
diff --git a/install/ui/ipa.css b/install/ui/ipa.css index 657bad7ee..d6f2f367e 100644 --- a/install/ui/ipa.css +++ b/install/ui/ipa.css @@ -178,15 +178,28 @@ div[name=settings].facet-group li a { float: right; } -.facet-controls a { - font-size: 1.3em !important; - margin: 0 16px 0 0; +.control-buttons { + float: left; +} + +.control-buttons a { + float: left; + font-size: 13px; + margin-right: 16px; + text-decoration: none; +} + +.facet-actions { + display: inline-block; + float: right; + margin-right: 8px; } /* --- Facet error --- */ .facet-error { padding: 2em 15em; + background-color: white; } .facet-error h1 { @@ -207,7 +220,6 @@ div[name=settings].facet-group li a { } .search-filter { - margin-top: -2px; display: inline-block; } diff --git a/install/ui/src/freeipa/details.js b/install/ui/src/freeipa/details.js index fcfd667dc..4d38aa3f1 100644 --- a/install/ui/src/freeipa/details.js +++ b/install/ui/src/freeipa/details.js @@ -632,6 +632,7 @@ exp.details_facet = IPA.details_facet = function(spec, no_init) { that.create_controls = function() { that.create_control_buttons(that.controls); + that.create_action_dropdown(that.controls); }; /** diff --git a/install/ui/src/freeipa/facet.js b/install/ui/src/freeipa/facet.js index 683575e8c..0e2e0506f 100644 --- a/install/ui/src/freeipa/facet.js +++ b/install/ui/src/freeipa/facet.js @@ -39,12 +39,13 @@ define([ './rpc', './spec_util', './text', + './widgets/ActionDropdownWidget', './dialog', './field', './widget' ], function(declare, lang, construct, on, Stateful, Evented, Singleton_registry, construct_utils, builder, IPA, $, - navigation, phases, reg, rpc, su, text) { + navigation, phases, reg, rpc, su, text, ActionDropdownWidget) { /** * Facet module @@ -204,7 +205,7 @@ exp.facet = IPA.facet = function(spec, no_init) { * Array of actions which are displayed in facet header * @property {Array.<string>} */ - that.header_actions = spec.header_actions; + that.header_actions = spec.header_actions || []; /** * Facet header @@ -590,7 +591,7 @@ exp.facet = IPA.facet = function(spec, no_init) { that.header.create(container); that.controls = $('<div/>', { - 'class': 'facet-controls' + 'class': 'facet-controls clearfix' }).appendTo(container); }; @@ -617,6 +618,13 @@ exp.facet = IPA.facet = function(spec, no_init) { } }; + that.create_action_dropdown = function(container) { + if (that.action_dropdown && that.header_actions && that.header_actions.length > 0) { + var dropdown = that.action_dropdown.render(); + container.append(dropdown); + } + }; + /** * Update h1 element in title container * @@ -962,12 +970,25 @@ exp.facet = IPA.facet = function(spec, no_init) { var buttons_spec = { $factory: IPA.control_buttons_widget, name: 'control-buttons', - 'class': 'control-buttons', + css_class: 'control-buttons', buttons: spec.control_buttons }; that.control_buttons = IPA.build(buttons_spec); that.control_buttons.init(that); + + that.action_dropdown = IPA.build({ + $ctor: ActionDropdownWidget, + action_names: that.header_actions, + name: 'facet_actions', + 'class': 'dropdown facet-actions', + right_aligned: true, + toggle_text: 'Actions ', + toggle_class: 'btn btn-default', + toggle_icon: 'fa fa-angle-down' + }); + that.action_dropdown.init(that); + }; if (!no_init) that.init_facet(); @@ -3038,9 +3059,8 @@ exp.control_buttons_widget = IPA.control_buttons_widget = function(spec) { */ that.create = function(container) { - that.container = $('<div/>', { - 'class': that['class'] - }).appendTo(container); + that.container = $('<div/>', {}).appendTo(container); + that.widget_create(that.container); for (var i=0; i<that.buttons.length; i++) { diff --git a/install/ui/src/freeipa/search.js b/install/ui/src/freeipa/search.js index 0a26dac9b..f9739f4c2 100644 --- a/install/ui/src/freeipa/search.js +++ b/install/ui/src/freeipa/search.js @@ -138,6 +138,7 @@ IPA.search_facet = function(spec, no_init) { }).appendTo(that.filter_container); that.create_control_buttons(that.controls); + that.create_action_dropdown(that.controls); }; that.managed_entity_pkey_prefix = function() { diff --git a/install/ui/src/freeipa/widgets/ActionDropdownWidget.js b/install/ui/src/freeipa/widgets/ActionDropdownWidget.js new file mode 100644 index 000000000..c43c79b54 --- /dev/null +++ b/install/ui/src/freeipa/widgets/ActionDropdownWidget.js @@ -0,0 +1,191 @@ +/* Authors: + * Petr Vobornik <pvoborni@redhat.com> + * + * Copyright (C) 2014 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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, see <http://www.gnu.org/licenses/>. +*/ +define(['dojo/_base/declare', + 'dojo/_base/lang', + 'dojo/on', + '../jquery', + './DropdownWidget'], function(declare, lang, on, $, DropdownWidget) { + + return declare([DropdownWidget], { + /** + * Represents and creates a dropdown widget for executing facet actions + * + * @class widgets.ActionDropdownWidget + */ + + /** + * Facet which contains actions + * @type {facet.facet|facets.Facet} + */ + facet: null, + + /** + * Names of actions, which should be later obtained from facet + * @property {Array.<string>} + */ + action_names: [], + + /** + * Actions + * @property {ordered_map} + */ + actions: [], + + on_item_click: function(event, item) { + + if (item.click) item.click(); + this.emit('item-click', item); + }, + + /** + * Initializes action list + * + * - set facet + * - get actions from facet + * - init child widgets + * + * @param {facet.facet} facet + */ + init: function(facet) { + + var options, actions, action, name, i; + + this.facet = facet; + + if (!this.action_names) return; + + for (i=0; i<this.action_names.length; i++) { + name = this.action_names[i]; + action = this.facet.actions.get(name); + this.add_action(action, true); + } + this.recreate_options(); + }, + + /** + * Add action + * @param {facet.action} action + * @param {boolean} [batch] Set to `true` when adding multiple actions to + * prevent unnecessary option initialization and + * recreation. Set it back to `false` when adding + * last option. + */ + add_action: function(action, batch) { + this.actions.put(action.name, action); + action.enabled_changed.attach(lang.hitch(this, this.action_enabled_changed)); + action.visible_changed.attach(lang.hitch(this, this.action_visible_changed)); + + if (!batch) { + this.recreate_options(); + } + }, + + /** + * Create and set select options from actions + */ + recreate_options: function() { + + var items, actions, action, i; + + items = []; + actions = this.actions.values; + + for (i=0; i< actions.length; i++) { + action = actions[i]; + if (!action.visible) continue; + items.push({ + label: action.label, + value: action.name, + name: action.name, + disabled: !action.enabled, + action: action + }); + } + + this.set('items', items); + }, + + on_item_click: function(event, item) { + + this.inherited(arguments); + if (item.action) { + this.execute_action(item.action); + } + }, + + + /** + * Execute action if enabled + * + * @protected + */ + execute_action: function(action) { + + if (action.enabled) { + action.execute(this.facet, + lang.hitch(this, this.on_action_success), + lang.hitch(this, this.on_action_error)); + } + }, + + /** + * Global action success handler + * + * @localdoc - override point + * @protected + * @abstract + */ + on_action_success: function() { + }, + + /** + * Global action error handler + * + * @localdoc - override point + * @protected + * @abstract + */ + on_action_error: function() { + }, + + /** + * Handle action's `enabled_changed` event. + * @protected + * @param {boolean} enabled + */ + action_enabled_changed: function(enabled) { + this.recreate_options(); + }, + + /** + * Handle action's `visible_changed` event. + * @protected + * @param {boolean} visible + */ + action_visible_changed: function(visible) { + this.recreate_options(); + }, + + constructor: function(spec) { + declare.safeMixin(this, spec); + this.actions = $.ordered_map(); + } + }); +}); diff --git a/install/ui/src/freeipa/widgets/DropdownWidget.js b/install/ui/src/freeipa/widgets/DropdownWidget.js index e45ea8945..181cfc5cf 100644 --- a/install/ui/src/freeipa/widgets/DropdownWidget.js +++ b/install/ui/src/freeipa/widgets/DropdownWidget.js @@ -77,6 +77,21 @@ define(['dojo/_base/declare', toggle_text: '', /** + * Icon displayed after toggle text + * @property {String} + */ + toggle_icon: null, + + /** + * Toggle classes + * + * e.g.: `btn btn-default` + * + * @property {String} + */ + toggle_class: '', + + /** * Toggle button content. Replaces toggle button text if set. Can be * use for more complex toggle buttons. * @property {HTMLElement|HTMLElement[]} @@ -96,6 +111,19 @@ define(['dojo/_base/declare', */ dom_node: null, + /** + * Container for items + * @protected + * @property {HTMLElement} + */ + ul_node: null, + + /** + * Menu is right aligned + * @type {Boolean} + */ + right_aligned: false, + render: function() { if (this.dom_node) { construct.empty(this.dom_node); @@ -108,7 +136,8 @@ define(['dojo/_base/declare', } this._render_toggle(this.dom_node); - this._render_items(this.items, this.dom_node); + this._render_list(this.dom_node); + this._render_items(this.items); return this.dom_node; }, @@ -120,6 +149,7 @@ define(['dojo/_base/declare', 'data-toggle': 'dropdown', href: '#' }); + if (this.toggle_class) dom_class.add(this.toggle_node, this.toggle_class); this._update_toggle(); if (container) { @@ -140,6 +170,11 @@ define(['dojo/_base/declare', } } else { prop.set(this.toggle_node, 'textContent', this.toggle_text); + if (this.toggle_icon) { + var icon = construct.create('i', { + 'class': this.toggle_icon + }, this.toggle_node); + } } }, @@ -153,30 +188,54 @@ define(['dojo/_base/declare', this._update_toggle(); }, - _render_items: function(items, container) { - var ul = construct.create('ul', { - 'class': 'dropdown-menu' - }); + _itemsSetter: function(value) { + this._clear_items(); + this.items = value; + this._render_items(this.items, this.dom_node); + }, - array.forEach(items, function(item) { - this._render_item(item, ul); - }, this); + _clear_items: function() { + this.items = []; + if (this.ul_node) { + construct.empty(this.ul_node); + } + }, + _render_list: function(container) { + + var ul = this.ul_node = construct.create('ul', { + 'class': 'dropdown-menu' + }); + if (this.right_aligned) { + dom_class.add(ul, 'dropdown-menu-right'); + } if (container) { construct.place(ul, container); } return ul; }, + _render_items: function(items, container) { + + var ul = this.ul_node; + array.forEach(items, function(item) { + this._render_item(item, ul); + }, this); + }, + _render_item: function(item, container) { var li = construct.create('li', { - 'data-name': item.name || '' + 'data-name': item.name || '', + role: 'presentation' }); var a = construct.create('a', { 'href': '#' + item.name || '' - }, li); + }); + if (item['class'] !== 'divider') { + construct.place(a, li); + } if (item.icon) { construct.create('i', { @@ -191,6 +250,11 @@ define(['dojo/_base/declare', dom_class.add(li, item['class']); } + if (item.disabled) { + dom_class.add(li, 'disabled'); + attr.set(a, 'tabIndex', -1); + } + if (item.items && item.items.length > 0) { dom_class.add(li, 'dropdown-submenu'); this._render_items(item.items, li); |