diff --git a/install/ui/doc/categories.json b/install/ui/doc/categories.json index 26e4cd6ea..93cadfe5d 100644 --- a/install/ui/doc/categories.json +++ b/install/ui/doc/categories.json @@ -38,6 +38,8 @@ "name": "Facets", "classes": [ "facet.facet", + "facets.ActionMixin", + "facets.HeaderMixin", "facets.Facet", "*_facet", "*Facet" diff --git a/install/ui/src/freeipa/facets/ActionMixin.js b/install/ui/src/freeipa/facets/ActionMixin.js new file mode 100644 index 000000000..4944c927c --- /dev/null +++ b/install/ui/src/freeipa/facets/ActionMixin.js @@ -0,0 +1,49 @@ +// +// Copyright (C) 2015 FreeIPA Contributors see COPYING for license +// + +define(['dojo/_base/declare', + '../builder', + '../facet' + ], + function(declare, builder, mod_facet) { + + +/** + * Header Mixin + * + * Extension of facet - actions + * + * @class facets.ActionMixin + */ +var ActionMixin = declare([], { + + /** + * State object for actions + * @property {facet.state} + */ + action_state: null, + + /** + * Collection of facet actions + * @property {facet.action_holder} + */ + actions: null, + + show: function() { + this.inherited(arguments); + this.actions.on_load(); + }, + + /** Constructor */ + constructor: function(spec) { + + this.action_state = builder.build('', spec.state || {}, {}, { $factory: mod_facet.state }); + this.actions = builder.build('', { actions: spec.actions }, {}, { $factory: mod_facet.action_holder } ); + this.action_state.init(this); + this.actions.init(this); + } +}); + +return ActionMixin; +}); \ No newline at end of file diff --git a/install/ui/src/freeipa/facets/Facet.js b/install/ui/src/freeipa/facets/Facet.js index 0608ab6fb..fb4b8a78c 100644 --- a/install/ui/src/freeipa/facets/Facet.js +++ b/install/ui/src/freeipa/facets/Facet.js @@ -70,6 +70,12 @@ define(['dojo/_base/declare', */ title: null, + /** + * Facet tab label + * @property {string} + */ + tab_label: null, + /** * Facet element's CSS class * @property {string} @@ -125,6 +131,10 @@ define(['dojo/_base/declare', */ state: null, + get_full_name: function() { + return this.name; + }, + /** * Checks if two objects has the same properties with equal values. * @@ -329,6 +339,7 @@ define(['dojo/_base/declare', this.preferred_container = spec.preferred_container; this.name = spec.name; this.label = text.get(spec.label); + this.tab_label = text.get(spec.tab_label || spec.label); this.title = text.get(spec.title || spec.label); this['class'] = spec['class']; this.container_node = spec.container_node; diff --git a/install/ui/src/freeipa/facets/HeaderMixin.js b/install/ui/src/freeipa/facets/HeaderMixin.js new file mode 100644 index 000000000..012731291 --- /dev/null +++ b/install/ui/src/freeipa/facets/HeaderMixin.js @@ -0,0 +1,259 @@ +// +// Copyright (C) 2015 FreeIPA Contributors see COPYING for license +// + +define(['dojo/_base/declare', + 'dojo/_base/lang', + 'dojo/on', + 'dojo/dom-construct', + 'dojo/dom-class', + '../builder', + '../facet', + '../widgets/ActionDropdownWidget' + ], + function(declare, lang, on, construct, dom_class, + builder, mod_facet, ActionDropdownWidget) { + + +/** + * Header Mixin + * + * Extension of facet - header with title and facet groups. Requires + * facets.ActionMixin. + * + * @class facets.HeaderMixin + */ +var HeaderMixin = declare([], { + + /** + * Facet header + * @property {facet.facet_header} + */ + header: null, + + /** + * Facet tabs are not displayed when set. + * @property {boolean} + */ + disable_facet_tabs: false, + + /** + * Facet tabs in sidebar + * + * There is and effort (#4625) to move all facet tabs into sidebar but it + * was not user tested, therefore they remain on the old place for the + * time being. + * + * This option should be changed when ^^ is removed. + * @property {boolean} + */ + tabs_in_sidebar: true, + + /** + * Array of actions which are displayed in facet header + * @property {Array.} + */ + header_actions: null, + + /** + * Facet groups + * + * @property {IPA.facet_group[]} + */ + facet_groups: null, + + /** + * Facet group name + * @property {string} + */ + facet_group: null, + + + /** + * Create facet's HTML representation + * NOTE: may be renamed to render + */ + create: function() { + + // this create method is Facet.create extended by header/sidebar logic + + if (this.dom_node) { + construct.empty(this.dom_node); + } else { + this.dom_node = construct.create('div', { + 'class': 'facet', + name: this.name, + 'data-name': this.name + }); + } + if (this['class']) { + dom_class.add(this.dom_node, this['class']); + } + if (this.container_node) { + construct.place(this.dom_node, this.container_node); + } + + var row = $('
', { + 'class': 'row' + }).appendTo(this.dom_node); + var content_cont = row; + + this.sidebar_content_el = $('
', { + 'class': mod_facet.sidebar_content_width + }).appendTo(row); + content_cont = $('
', { + 'class': 'row' + }).appendTo(this.sidebar_content_el); + + this.sidebar_el = $('
', { + 'class': mod_facet.sidebar_class + mod_facet.sidebar_width + }).appendTo(row); + + this.header_container = $('
', { + 'class': 'facet-header col-sm-12' + }).appendTo(content_cont); + this.create_header(this.header_container); + + this.content = $('
', { + 'class': 'facet-content col-sm-12' + }).appendTo(content_cont); + + + this.children_node = this.content[0]; + return this.dom_node; + }, + + /** + * Create control buttons + * + * @param {jQuery} container + * @protected + */ + create_header: function(container) { + + this.header.create(container); + + this.controls = $('
', { + 'class': 'facet-controls clearfix' + }).appendTo(container); + + this.controls_left = $('
', { + 'class': 'facet-controls-left' + }).appendTo(this.controls); + + this.controls_right = $('
', { + 'class': 'facet-controls-right' + }).appendTo(this.controls); + + this.create_controls(); + }, + + /** + * Create header controls + * + * - ie control buttons orActionDropDown + */ + create_controls: function() { + + this.create_control_buttons(this.controls_left); + this.create_action_dropdown(this.controls_left); + }, + + /** + * Create control buttons + * + * @param {jQuery} container + * @protected + */ + create_control_buttons: function(container) { + + if (this.control_buttons) { + this.control_buttons.create(container); + } + }, + + /** + * Create action dropdown widget in supplied container + * + * @param {jQuery} container + * @protected + */ + create_action_dropdown: function(container) { + if (this.action_dropdown && this.header_actions && this.header_actions.length > 0) { + var dropdown = this.action_dropdown.render(); + container.append(dropdown); + } + }, + + /** + * Display or hide facet tabs - either in sidebar or facet header + * @param {boolean} visible + */ + set_tabs_visible: function(visible) { + + if (this.disable_facet_tabs) return; + if (this.tabs_in_sidebar && this.sidebar_el) { + var a = visible ? mod_facet.sidebar_content_width : mod_facet.sidebar_content_full_width; + var r = visible ? mod_facet.sidebar_content_full_width : mod_facet.sidebar_content_width; + this.sidebar_content_el.removeClass(r); + this.sidebar_content_el.addClass(a); + this.sidebar_el.css('display', visible ? '' : 'none'); + } + this.header.set_tabs_visible(visible); + }, + + /** + * Overrides parent's object(usually facet.Facet) show method. To select a + * tab. + */ + show: function() { + this.inherited(arguments); + this.header.select_tab(); + }, + + /** Constructor */ + constructor: function(spec) { + + this.facet_groups = builder.build('', spec.facet_groups, {}, { + $factory: mod_facet.facet_group + }); + this.facet_group = spec.facet_group; + + this.header = builder.build( + '', + spec.header || { init_group_names: true}, + {}, + { + $pre_ops: [{ facet: this }], + $factory: mod_facet.simple_facet_header + } + ); + this.header.init(); + this.header_actions = spec.header_actions || []; + + var buttons_spec = { + $factory: mod_facet.control_buttons_widget, + name: 'control-buttons', + css_class: 'control-buttons', + buttons: spec.control_buttons + }; + + this.control_buttons = builder.build(null, buttons_spec); + this.control_buttons.init(this); + + this.action_dropdown = builder.build(null, { + $ctor: ActionDropdownWidget, + action_names: this.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' + }); + this.action_dropdown.init(this); + } +}); + +return HeaderMixin; +}); \ No newline at end of file