* Addressbook: use a hierarchical list to show distribution lists incl. groups (if groups are enabled)

allow to specify widget and placeholder for NM filter(2) and cat
This commit is contained in:
ralf 2025-02-20 15:18:59 +01:00
parent ef4d4abb2b
commit 327c72413e
5 changed files with 46 additions and 16 deletions

View File

@ -244,6 +244,8 @@ class addressbook_ui extends addressbook_bo
'filter' => '', // =All // IO filter, if not 'no_filter' => True
'filter_no_lang' => True, // I set no_lang for filter (=dont translate the options)
'no_filter2' => True, // I disable the 2. filter (params are the same as for filter)
'filter2_widget' => 'et2-tree-dropdown',
'filter2_placeholder' => lang('No distribution list'),
//'filter2_label'=> lang('Distribution lists'), // IO filter2, if not 'no_filter2' => True
'filter2' => '', // IO filter2, if not 'no_filter2' => True
'filter2_no_lang'=> True, // I set no_lang for filter2 (=dont translate the options)
@ -348,7 +350,7 @@ class addressbook_ui extends addressbook_bo
{
$this->tmpl->disableElement('nm[col_filter][tid]');
}
// get the availible grouped-views plus the label of the contacts view of one group
// get the available grouped-views plus the label of the contacts view of one group
$sel_options['grouped_view'] = $this->grouped_views;
if (isset($grouped_view))
{

View File

@ -3554,8 +3554,9 @@ export class et2_nextmatch_header_bar extends et2_DOMWidget implements et2_INext
if(!settings.no_cat)
{
if(typeof settings.cat_id_label == 'undefined') settings.cat_id_label = '';
this.category = this._build_select('cat_id', settings.cat_is_select ?
'et2-select' : 'et2-select-cat', settings.cat_id, settings.cat_is_select !== true, {
this.category = this._build_select('cat_id', settings.cat_widget ?? (settings.cat_is_select ?
'et2-select' : 'et2-select-cat'), settings.cat_id, settings.cat_is_select !== true, {
placeholder: settings.cat_placeholder,
multiple: false,
class: "select-cat",
value_class: settings.cat_id_class
@ -3565,14 +3566,17 @@ export class et2_nextmatch_header_bar extends et2_DOMWidget implements et2_INext
// Filter 1
if(!settings.no_filter)
{
this.filter = this._build_select('filter', 'et2-select', settings.filter, settings.filter_no_lang);
this.filter = this._build_select('filter', settings.filter_widget ?? 'et2-select', settings.filter, settings.filter_no_lang, {
placeholder: settings.filter_placeholder,
});
}
// Filter 2
if(!settings.no_filter2)
{
this.filter2 = this._build_select('filter2', 'et2-select', settings.filter2,
this.filter2 = this._build_select('filter2', settings.filter2_widget ?? 'et2-select', settings.filter2,
settings.filter2_no_lang, {
placeholder: settings.filter2_placeholder,
multiple: false,
class: "select-cat",
value_class: settings.filter2_class

View File

@ -15,6 +15,7 @@
namespace EGroupware\Api\Contacts;
use EGroupware\Api;
use EGroupware\Api\Etemplate\Widget\Tree;
/**
* Contacts storage object
@ -1204,15 +1205,28 @@ class Storage
if ($GLOBALS['egw_info']['user']['preferences']['addressbook']['hide_accounts'] !== '1' &&
$GLOBALS['egw_info']['user']['preferences']['addressbook']['hide_groups_as_lists'] !== '1')
{
foreach($GLOBALS['egw']->accounts->search(array(
'type' => 'groups'
)) as $account_id => $group)
{
if ($GLOBALS['egw_info']['user']['preferences']['addressbook']['hide_groups_as_lists'] === '0' || !empty($group['account_email']))
unset($lists['']);
return array_merge([
[Tree::ID => 0, Tree::LABEL => lang('No distribution list')], // empty label
// add distribution lists in a (by default) open container "Distribution lists"
[
Tree::ID => '0',
Tree::LABEL => lang('Distribution lists'),
Tree::IMAGE_FOLDER_OPEN => Api\Image::find('api', 'dhtmlxtree/folderOpen'),
Tree::IMAGE_FOLDER_CLOSED => Api\Image::find('api', 'dhtmlxtree/folderClosed'),
Tree::OPEN => true,
Tree::UNSELECTABLE => true,
Tree::CHILDREN => array_values(array_map(static function($label, $key)
{
$lists[(string)$account_id] = Api\Accounts::format_username($group['account_lid'], '', '', $account_id);
}
}
return [Tree::ID => $key, Tree::LABEL => $label, Tree::IMAGE_LEAF => 'list'];
}, $lists, array_keys($lists)))],
],
// add the groups behind also using containers, if defined (taking into account the pref which groups to show)
Tree::groups('', $GLOBALS['egw_info']['user']['preferences']['addressbook']['hide_groups_as_lists'] === '0' ? null :
static function($group)
{
return !empty($group['account_email']);
}));
}
return $lists;

View File

@ -28,7 +28,9 @@ use EGroupware\Api;
* 'no_filter2' => True// I disable the 2. filter (params are the same as for filter)
* 'no_cat' => True// I disable the cat-selectbox
* 'cat_app' => // I application the cat's should be from, default app in get_rows
* 'cat_is_select' => // I true||'no_lang' use selectbox instead of category selection, default null
* 'cat_is_select' => // I true||'no_lang' use selectbox instead of category selection, default null (cat_widget has higher precedence!)
* '(filter|filter2|cat)_widget' => // I widget to use instead of the regular et2-select(-cat)
* '(filter|filter2|cat)_placeholder' => // I placeholder-text to use
* 'template' => // I template to use for the rows, if not set via options
* 'header_left' => // I template to show left of the range-value, left-aligned (optional)
* 'header_right' => // I template to show right of the range-value, right-aligned (optional)

View File

@ -113,6 +113,11 @@ class Tree extends Etemplate\Widget
*/
const CLASS_LIST = 'class';
/**
* Container which can be opened/closed, but not selected
*/
const UNSELECTABLE = 'unselectable';
/**
* Constructor
*
@ -548,7 +553,7 @@ class Tree extends Etemplate\Widget
// store link as userdata, maybe we should store everything not directly understood by tree this way ...
foreach(array_diff_key($data, array_flip([
self::ID, self::LABEL, self::TOOLTIP, self::IMAGE_LEAF, self::IMAGE_FOLDER_OPEN, self::IMAGE_FOLDER_CLOSED,
'item', self::AUTOLOAD_CHILDREN, 'select', self::OPEN, 'call',
self::CHILDREN, self::AUTOLOAD_CHILDREN, 'select', self::OPEN, 'call', self::UNSELECTABLE,
])) as $name => $content)
{
$data['userdata'][] = array(
@ -565,9 +570,10 @@ class Tree extends Etemplate\Widget
* Get list of all groups as tree, taking container into account, if enabled
*
* @param string $root root for building tree-IDs, "" for just using IDs, no path
* @param ?callable $check function to check if group should be added
* @return array[] with tree-children, groups have IDs $root/$account_id (independent of container!), while container use $root/md5($container_name)
*/
public static function groups(string $root='/groups')
public static function groups(string $root='/groups', ?callable $check=null)
{
if ($root) $root = rtrim($root, '/').'/';
@ -579,6 +585,7 @@ class Tree extends Etemplate\Widget
'start' => false, // to NOT limit number of returned groups
)) as $group)
{
if ($check && !$check($group)) continue;
if (($container_name = Api\Accounts::container($group)))
{
foreach($children as &$container)
@ -592,6 +599,7 @@ class Tree extends Etemplate\Widget
Tree::ID => $root.md5($container_name),
Tree::IMAGE_FOLDER_OPEN => Api\Image::find('api', 'dhtmlxtree/folderOpen'),
Tree::IMAGE_FOLDER_CLOSED => Api\Image::find('api', 'dhtmlxtree/folderClosed'),
Tree::UNSELECTABLE => true,
Tree::CHILDREN => [],
]);
$container =& $children[count($children)-1];