mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 00:29:38 +01:00
Add select account search dialog
This commit is contained in:
parent
c0ae7013a5
commit
de01faf0df
@ -120,6 +120,13 @@ class etemplate_widget_menupopup extends etemplate_widget
|
||||
if (!is_array(self::$request->sel_options[$form_name])) self::$request->sel_options[$form_name] = array();
|
||||
if ($this->attrs['type'])
|
||||
{
|
||||
// Check selection preference, we may be able to skip reading some data
|
||||
$select_pref = $GLOBALS['egw_info']['user']['preferences']['common']['account_selection'];
|
||||
if(!$GLOBALS['egw_info']['apps']['admin'] && $select_pref == 'none')
|
||||
{
|
||||
$this->attrs['readonly'] = true;
|
||||
}
|
||||
|
||||
// += to keep further options set by app code
|
||||
self::$request->sel_options[$form_name] += self::typeOptions($this->attrs['type'],
|
||||
// typeOptions thinks # of rows is the first thing in options
|
||||
@ -300,7 +307,10 @@ class etemplate_widget_menupopup extends etemplate_widget
|
||||
'title' => empty($cat['description']) ? $s : $cat['description'],
|
||||
);
|
||||
// Send data too
|
||||
$options[$cat['id']] += $cat['data'];
|
||||
if(is_array($cat['data']))
|
||||
{
|
||||
$options[$cat['id']] += $cat['data'];
|
||||
}
|
||||
}
|
||||
// preserv unavailible cats (eg. private user-cats)
|
||||
/* TODO
|
||||
@ -316,8 +326,12 @@ class etemplate_widget_menupopup extends etemplate_widget
|
||||
|
||||
case 'select-account': // options: #rows,{accounts(default)|both|groups|owngroups},{0(=lid)|1(default=name)|2(=lid+name),expand-multiselect-rows,not-to-show-accounts,...)}
|
||||
//echo "<p>select-account widget: name=$cell[name], type='$type', rows=$rows, readonly=".(int)($cell['readonly'] || $readonlys)."</p>\n";
|
||||
|
||||
// Get preference for selection display
|
||||
$select_pref = $GLOBALS['egw_info']['user']['preferences']['common']['account_selection'];
|
||||
|
||||
// in case of readonly, we read/create only the needed entries, as reading accounts is expensive
|
||||
if ($readonly)
|
||||
if ($readonly || $select_pref == 'popup')
|
||||
{
|
||||
$no_lang = True;
|
||||
if (!is_array($value) && strpos($value,',') !== false) $value = explode(',',$value);
|
||||
@ -328,42 +342,21 @@ class etemplate_widget_menupopup extends etemplate_widget
|
||||
}
|
||||
break;
|
||||
}
|
||||
if($type == 'owngroups')
|
||||
if($type == 'owngroups' || $select_pref == 'groupmembers')
|
||||
{
|
||||
$type = 'groups';
|
||||
$owngroups = true;
|
||||
foreach($GLOBALS['egw']->accounts->membership() as $group) $mygroups[] = $group['account_id'];
|
||||
}
|
||||
/* account-selection for hughe number of accounts
|
||||
if ($this->ui == 'html' && $type != 'groups') // use eGW's new account-selection (html only)
|
||||
elseif (in_array($type, array('accounts', 'both')) && $select_pref == 'primary_group')
|
||||
{
|
||||
$not = array_slice(explode(',',$cell['size']),4);
|
||||
$help = (int)$no_lang < 2 ? lang($cell['help']) : $cell['help'];
|
||||
$onFocus = "self.status='".addslashes(htmlspecialchars($help))."'; return true;";
|
||||
$onBlur = "self.status=''; return true;";
|
||||
if ($cell['noprint'])
|
||||
{
|
||||
foreach(is_array($value) ? $value : (strpos($value,',') !== false ? explode(',',$value) : array($value)) as $id)
|
||||
{
|
||||
if ($id) $onlyPrint[] = self::accountInfo($id,$acc,$type2,$type=='both');
|
||||
}
|
||||
$onlyPrint = $onlyPrint ? implode('<br />',$onlyPrint) : lang((int)$rows < 0 ? 'all' : $rows);
|
||||
$noPrint_class = ' class="noPrint"';
|
||||
}
|
||||
if (($rows > 0 || $type3) && substr($name,-2) != '[]') $name .= '[]';
|
||||
$value = $GLOBALS['egw']->uiaccountsel->selection($name,'eT_accountsel_'.str_replace(array('[','][',']'),array('_','_',''),$name),
|
||||
$value,$type,$rows > 0 ? $rows : ($type3 ? -$type3 : 0),$not,' onfocus="'.$onFocus.'" onblur="'.$onBlur.'"'.$noPrint_class,
|
||||
$cell['onchange'] == '1' ? 'this.form.submit();' : $cell['onchange'],
|
||||
!empty($rows) && 0+$rows <= 0 ? lang($rows < 0 ? 'all' : $rows) : False);
|
||||
if ($cell['noprint'])
|
||||
{
|
||||
$value = '<span class="onlyPrint">'.$onlyPrint.'</span>'.$value;
|
||||
}
|
||||
$cell['type'] = 'html';
|
||||
$cell['size'] = ''; // is interpreted as link otherwise
|
||||
etemplate::$request->set_to_process($name,'select');
|
||||
break;
|
||||
}*/
|
||||
$owngroups = true;
|
||||
$mygroups[] = $GLOBALS['egw_info']['user']['primary_group'];
|
||||
}
|
||||
|
||||
// Popup is the only preference option that doesn't need more select options
|
||||
if($select_pref == 'popup') break;
|
||||
|
||||
$no_lang = True;
|
||||
$accs = $GLOBALS['egw']->accounts->get_list(empty($type) ? 'accounts' : $type); // default is accounts
|
||||
foreach($accs as $acc)
|
||||
|
@ -19,6 +19,418 @@
|
||||
et2_widget_link;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Account selection widget
|
||||
* Changes according to the user's account_selection preference
|
||||
* - 'none' => Server-side: the read-only widget is used
|
||||
* - 'groupmembers' => Non admins can only select groupmembers (Server side - normal selectbox)
|
||||
* - 'selectbox' => Selectbox with all accounts and groups (Server side - normal selectbox)
|
||||
* - 'primary_group' => Selectbox with primary group and search
|
||||
* - 'popup' => Empty selectbox with search
|
||||
*
|
||||
* Only primary_group and popup need anything different from a normal selectbox
|
||||
*/
|
||||
var et2_selectAccount = et2_selectbox.extend({
|
||||
|
||||
attributes: {
|
||||
'account_type': {
|
||||
'name': 'Account type',
|
||||
'default': 'accounts',
|
||||
'type': 'string',
|
||||
'description': 'Limit type of accounts. One of {accounts,groups,both,owngroups}.'
|
||||
}
|
||||
},
|
||||
|
||||
legacyOptions: ['empty_label','account_type'],
|
||||
|
||||
account_types: ['accounts','groups','both','owngroups'],
|
||||
|
||||
init: function(_parent, _attrs) {
|
||||
|
||||
// Type in rows or somewhere else?
|
||||
if(jQuery.inArray(_attrs['empty_label'], this.account_types) > 0 && (
|
||||
jQuery.inArray(_attrs['account_type'], this.account_types) < 0 ||
|
||||
_attrs['account_type'] == this.attributes.account_type.default)
|
||||
)
|
||||
{
|
||||
_attrs['account_type'] = _attrs['empty_label']
|
||||
_attrs['empty_label'] = '';
|
||||
}
|
||||
if(jQuery.inArray(_attrs['account_type'], this.account_types) < 0)
|
||||
{
|
||||
this.egw().debug("warn", "Invalid account_type: %s Valid options:",_attrs['account_type'], this.account_types);
|
||||
}
|
||||
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
// Holder for search jQuery nodes
|
||||
this.search = null;
|
||||
|
||||
// Reference to object with dialog
|
||||
this.dialog = null;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* Single selection - override to add search button
|
||||
*/
|
||||
createInputWidget: function() {
|
||||
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
// Add search button
|
||||
var type = this.egw().preference('account_selection', 'common');
|
||||
if(type == 'primary_group' || type == 'popup')
|
||||
{
|
||||
var button = jQuery(document.createElement("span"))
|
||||
.addClass("et2_clickable")
|
||||
.click(this, this._open_search)
|
||||
.append('<span class="ui-icon ui-icon-search" style="display:inline-block"/>')
|
||||
|
||||
this.getSurroundings().insertDOMNode(button[0]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Multiple selection - override to add search button
|
||||
*/
|
||||
createMultiSelect: function() {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
// Add search button
|
||||
var button = jQuery(document.createElement("li"))
|
||||
.addClass("et2_clickable")
|
||||
.click(this, this._open_multi_search)
|
||||
.append('<span class="ui-icon ui-icon-search"/>')
|
||||
.append("<span>"+this.egw().lang('search')+"</span>");
|
||||
var type = this.egw().preference('account_selection', 'common');
|
||||
|
||||
// Put it first so check/uncheck don't move around
|
||||
this.multiOptions.prev().show().find('ul')
|
||||
.prepend(button);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create & display a way to search & select a single account / group
|
||||
* Single selection is just link widget
|
||||
*/
|
||||
_open_search: function(e) {
|
||||
var widget = e.data;
|
||||
var search = widget._create_search();
|
||||
|
||||
// Selecting a single user closes the dialog, this only used if user cleared
|
||||
var ok_click = function() {
|
||||
jQuery(this).dialog("close");
|
||||
widget.set_value([]);
|
||||
// Free it up, it will be re-created, if ever needed again
|
||||
jQuery(this).dialog("destroy");
|
||||
};
|
||||
widget._create_dialog(search, ok_click);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create & display a way to search & select multiple accounts / groups
|
||||
*/
|
||||
_open_multi_search: function(e) {
|
||||
var widget = e.data;
|
||||
var table = widget.search = jQuery('<table><tbody><tr valign="top"><td id="search_col"/><td id="selection_col"/></tr></tbody></table>');
|
||||
table.css("width", "100%").css("height", "100%");
|
||||
var search_col = jQuery('#search_col',table);
|
||||
var select_col = jQuery('#selection_col',table);
|
||||
|
||||
// Search / Selection
|
||||
search_col.append(widget._create_search());
|
||||
|
||||
// Currently selected
|
||||
select_col.append(widget._create_selected());
|
||||
|
||||
var ok_click = function() {
|
||||
jQuery(this).dialog("close");
|
||||
// Update widget with selected
|
||||
var ids = [];
|
||||
var data = {};
|
||||
jQuery('#selected li',select_col).each(function() {
|
||||
// Remove sel_ prefix and add to list
|
||||
ids.push(this.id.substr(4));
|
||||
|
||||
// Make sure option is there
|
||||
if(jQuery('input[id$="_opt_'+this.id.substr(4)+'"]',widget.multiOptions).length == 0)
|
||||
{
|
||||
widget._appendMultiOption(this.id.substr(4),jQuery('label',this).text());
|
||||
}
|
||||
});
|
||||
|
||||
widget.set_value(ids);
|
||||
|
||||
// Free it up, it will be re-created, if ever needed again
|
||||
jQuery(this).dialog("destroy");
|
||||
};
|
||||
|
||||
var container = jQuery(document.createElement("div")).append(table);
|
||||
return widget._create_dialog(container, ok_click);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create / display popup with search / selection widgets
|
||||
*/
|
||||
_create_dialog: function(widgets, update_function) {
|
||||
this.dialog = widgets;
|
||||
widgets.dialog({
|
||||
title: this.options.label ? this.options.label : this.egw().lang('Select'),
|
||||
modal: true,
|
||||
// Static size for easier layout
|
||||
width: "500",
|
||||
height: "350",
|
||||
buttons: [{
|
||||
text: this.egw().lang("ok"),
|
||||
click: update_function
|
||||
},{
|
||||
text: this.egw().lang("cancel"),
|
||||
click: function() {
|
||||
jQuery(this).dialog("close");
|
||||
jQuery(this).dialog("destroy");
|
||||
}}
|
||||
]
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Search is a link-entry widget, with some special display for multi-select
|
||||
*/
|
||||
_create_search: function() {
|
||||
var self = this;
|
||||
var search = this.search = jQuery(document.createElement("div"));
|
||||
|
||||
var search_widget = this.search_widget = et2_createWidget('link-entry', {
|
||||
'application': 'home-accounts',
|
||||
'query': function(request, response) {
|
||||
// Clear previous search results for multi-select
|
||||
if(!request.options)
|
||||
{
|
||||
search.find('#search_results').empty();
|
||||
}
|
||||
// Restrict to specified account type
|
||||
if(!request['options'] || !request['options']['filter'])
|
||||
{
|
||||
request['options'] = {filter:{group:self.options.account_type}};
|
||||
}
|
||||
return true;
|
||||
},
|
||||
'select': function(e, selected) {
|
||||
// Make sure option is there
|
||||
if(typeof self.options.select_options[selected.item.value] == 'undefined')
|
||||
{
|
||||
self.options.select_options[selected.item.value] = selected.item;
|
||||
self._appendOptionElement(selected.item.value, selected.item.label);
|
||||
}
|
||||
self.set_value(selected.item.value);
|
||||
if(self.dialog)
|
||||
{
|
||||
self.dialog.dialog("close");
|
||||
self.dialog.dialog("destroy");
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
// select widget doesn't allow children, so add it
|
||||
search.append(search_widget.getDOMNode());
|
||||
|
||||
if(!this.options.multiple) return search;
|
||||
|
||||
// Multiple is more complicated. It uses a custom display for results to
|
||||
// allow choosing multiples from a match
|
||||
var results = jQuery(document.createElement("ul"))
|
||||
.attr("id", "search_results")
|
||||
.css("height", "230px")
|
||||
.addClass("ui-multiselect-checkboxes ui-helper-reset");
|
||||
jQuery(document.createElement("div"))
|
||||
.addClass("et2_selectbox")
|
||||
.css("height", "100%")
|
||||
.append(results)
|
||||
.appendTo(search);
|
||||
|
||||
// Override link-entry auto-complete for custom display
|
||||
// Don't show normal drop-down
|
||||
search_widget.search.data("autocomplete")._suggest = function(items) {
|
||||
jQuery.each(items, function (index, item) {
|
||||
self._add_search_result(results, item);
|
||||
});
|
||||
}
|
||||
|
||||
return search;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add the selected result to the list of search results
|
||||
*/
|
||||
_add_search_result: function(list, item) {
|
||||
|
||||
var node = null;
|
||||
var self = this;
|
||||
|
||||
// (containter of) Currently selected users / groups
|
||||
var selected = jQuery('#selected', this.dialog);
|
||||
|
||||
// Group
|
||||
if(item.value && item.value < 0)
|
||||
{
|
||||
node = jQuery(document.createElement('ul'));
|
||||
// Add button to show users
|
||||
if(this.options.account_type != 'groups')
|
||||
{
|
||||
jQuery('<span class="ui-icon ui-icon-circlesmall-plus et2_clickable"/>')
|
||||
.css("float", "left")
|
||||
.appendTo(node)
|
||||
.toggle(function() {
|
||||
jQuery(this).removeClass("ui-icon-circlesmall-plus")
|
||||
.addClass("ui-icon-circlesmall-minus");
|
||||
|
||||
var group = jQuery(this).parent()
|
||||
.addClass("expanded");
|
||||
|
||||
if(group.children("li").length == 0)
|
||||
{
|
||||
// Fetch group members
|
||||
self.search_widget.query({term:"",options: {filter:{group: item.value}}}, function(items) {
|
||||
jQuery(items).each(function(index,item) {
|
||||
self._add_search_result(node, item);
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
group.children("li")
|
||||
// Only show children that are not selected
|
||||
.each(function(index, item) {
|
||||
var j = jQuery(item);
|
||||
if(jQuery('#sel_'+j.attr("id").substr(5),selected).length == 0)
|
||||
{
|
||||
j.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
},function() {
|
||||
jQuery(this).addClass("ui-icon-circlesmall-plus")
|
||||
.removeClass("ui-icon-circlesmall-minus");
|
||||
|
||||
var group = jQuery(this).parent().children("li").hide();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
// User
|
||||
else if (item.value)
|
||||
{
|
||||
node = jQuery(document.createElement('li'));
|
||||
}
|
||||
node.attr("id", "list_"+item.value);
|
||||
|
||||
jQuery('<span class="ui-icon ui-icon-arrow-1-e et2_clickable"/>')
|
||||
.css("float", "right")
|
||||
.appendTo(node)
|
||||
.click(function() {
|
||||
var button = jQuery(this);
|
||||
self._add_selected(selected, button.parent().attr("id").substr(5));
|
||||
// Hide user, but only hide button for group
|
||||
if(button.parent().is('li'))
|
||||
{
|
||||
button.parent().hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
button.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// If already in list, hide it
|
||||
if(jQuery('#sel_'+item.value,selected).length != 0)
|
||||
{
|
||||
node.hide();
|
||||
}
|
||||
|
||||
var label = jQuery(document.createElement('label'))
|
||||
.addClass("loading")
|
||||
.appendTo(node);
|
||||
this.egw().link_title('home-accounts', item.value, function(name) {
|
||||
label.text(name).removeClass("loading")
|
||||
}, label);
|
||||
|
||||
node.appendTo(list)
|
||||
},
|
||||
|
||||
_create_selected: function() {
|
||||
var node = jQuery(document.createElement("div"))
|
||||
.addClass("et2_selectbox");
|
||||
|
||||
var header = jQuery(document.createElement("div"))
|
||||
.addClass("ui-widget-header ui-helper-clearfix")
|
||||
.appendTo(node);
|
||||
|
||||
var selected = jQuery(document.createElement("ul"))
|
||||
.addClass("ui-multiselect-checkboxes ui-helper-reset")
|
||||
.attr("id", "selected")
|
||||
.css("height", "230px")
|
||||
.appendTo(node);
|
||||
|
||||
jQuery(document.createElement("span"))
|
||||
.text(this.egw().lang("Selection"))
|
||||
.addClass("ui-multiselect-header")
|
||||
.appendTo(header);
|
||||
|
||||
var controls = jQuery(document.createElement("ul"))
|
||||
.addClass('ui-helper-reset')
|
||||
.appendTo(header);
|
||||
|
||||
jQuery(document.createElement("li"))
|
||||
.addClass("et2_clickable")
|
||||
.click(selected, function(e) {jQuery("li",e.data).remove();})
|
||||
.append('<span class="ui-icon ui-icon-closethick"/>')
|
||||
.append("<span>"+this.egw().lang('Remove all')+"</span>")
|
||||
.appendTo(controls);
|
||||
|
||||
// Add in currently selected
|
||||
if(this.getValue())
|
||||
{
|
||||
var value = this.getValue();
|
||||
for(var i = 0; i < value.length; i++) {
|
||||
this._add_selected(selected, value[i]);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add an option to the list of selected accounts
|
||||
* value is the account / group ID
|
||||
*/
|
||||
_add_selected: function(list, value) {
|
||||
|
||||
var option = jQuery(document.createElement('li'))
|
||||
.attr("id",'sel_'+value)
|
||||
.appendTo(list);
|
||||
jQuery('<span class="ui-icon ui-icon-close et2_clickable"/>')
|
||||
.css("float", "right")
|
||||
.appendTo(option)
|
||||
.click(function() {
|
||||
var id = jQuery(this).parent().attr("id").substr(4);
|
||||
jQuery(this).parent().remove();
|
||||
// Add 'add' button back, if in results list
|
||||
list.parents("tr").find("#list_"+id).show()
|
||||
// Show button(s) for group
|
||||
.children('span').show();
|
||||
});
|
||||
|
||||
var label = jQuery(document.createElement('label'))
|
||||
.addClass("loading")
|
||||
.appendTo(option);
|
||||
this.egw().link_title('home-accounts', value, function(name) {this.text(name).removeClass("loading")}, label);
|
||||
}
|
||||
});
|
||||
et2_register_widget(et2_selectAccount, ["select-account"]);
|
||||
|
||||
|
||||
/**
|
||||
* et2_selectAccount_ro is the readonly implementation of select account
|
||||
* It extends et2_link to avoid needing the whole user list on the client.
|
||||
|
@ -211,6 +211,18 @@ button.et2_button_text:focus, input[type=button]:focus {
|
||||
list-style-type: none;
|
||||
text-indent: -26px;
|
||||
}
|
||||
.et2_selectbox .ui-multiselect-checkboxes ul {
|
||||
margin: 0px auto;
|
||||
padding-left: 0px;
|
||||
clear:both;
|
||||
text-decoration: none;
|
||||
list-style-image: none;
|
||||
list-style-type: none;
|
||||
}
|
||||
.et2_selectbox .ui-multiselect-checkboxes ul>label {
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
|
||||
.et2_selectbox .ui-multiselect-checkboxes label {
|
||||
display: block;
|
||||
border: 1px solid transparent;
|
||||
@ -234,6 +246,10 @@ ul.et2_selectbox {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select account dialog
|
||||
*/
|
||||
|
||||
/**
|
||||
* Date / Time widgets
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user