diff --git a/admin/inc/class.admin_ui.inc.php b/admin/inc/class.admin_ui.inc.php
index 8341db90b4..62d3289526 100644
--- a/admin/inc/class.admin_ui.inc.php
+++ b/admin/inc/class.admin_ui.inc.php
@@ -62,6 +62,16 @@ class admin_ui
'actions' => self::user_actions(),
'placeholder_actions' => array('add')
);
+ $content['groups'] = array(
+ 'get_rows' => 'admin_ui::get_groups',
+ 'no_cat' => true,
+ 'no_filter' => true,
+ 'no_filter2' => true,
+ 'row_id' => 'account_id',
+ 'actions' => self::group_actions(),
+ 'placeholder_actions' => array('add')
+ );
+
//$content['msg'] = 'Hi Ralf ;-)';
$sel_options['tree'] = $this->tree_data();
$sel_options['filter'] = array('' => lang('All groups'));
@@ -108,80 +118,16 @@ class admin_ui
*/
public static function tree_actions()
{
- $user_actions = self::user_actions();
+ $actions = static::group_actions();
- $actions = array(
- 'view' => array(
- 'onExecute' => 'javaScript:app.admin.group',
- 'caption' => 'Show members',
- 'enableId' => '^/groups/-\\d+',
- 'default' => true,
- 'group' => $group=1,
- ),
- 'add' => array(
- 'group' => $group,
- )+$user_actions['add'],
- 'acl' => array(
- 'onExecute' => 'javaScript:app.admin.group',
- 'caption' => 'Access control',
- 'enableId' => '^/groups/-\\d+',
- 'url' => 'menuaction=admin.admin_acl.index&account_id=$id',
- 'popup' => '900x450',
- 'icon' => 'lock',
- 'group' => 2,
- ),
- );
- if (!$GLOBALS['egw']->acl->check('account_access',64,'admin')) // no rights to set ACL-rights
+ foreach($actions as $action_id => &$action)
{
- $actions['deny'] = array(
- 'caption' => 'Deny access',
- 'enableId' => '^/groups/-\\d+',
- 'url' => 'menuaction=admin.admin_denyaccess.list_apps&account_id=$id',
- 'onExecute' => 'javaScript:app.admin.group',
- 'icon' => 'cancel',
- 'group' => 2,
- );
- }
- $group = 5; // allow to place actions in different groups by hook, this is the default
- // supporting both old way using $GLOBALS['menuData'] and new just returning data in hook
- $apps = array_unique(array_merge(array('admin'), Api\Hooks::implemented('edit_group')));
- foreach($apps as $app)
- {
- $GLOBALS['menuData'] = $data = array();
- $data = Api\Hooks::single('edit_group', $app);
- if (!is_array($data)) $data = $GLOBALS['menuData'];
- //error_log(__METHOD__."() app $app returned ".array2string($data));
- foreach($data as $item)
+ if (!isset($action['enableId']) && !in_array($action_id, array('add')))
{
- // allow hook to return "real" actions, but still support legacy: description, url, extradata, options
- if (empty($item['caption']))
- {
- $item['caption'] = $item['description'];
- unset($item['description']);
- }
- if (isset($item['url']) && isset($item['extradata']))
- {
- $item['url'] = $item['extradata'].'&account_id=$id';
- $item['id'] = substr($item['extradata'], 11);
- unset($item['extradata']);
- $matches = null;
- if ($item['options'] && preg_match('/(egw_openWindowCentered2?|window.open)\([^)]+,(\d+),(\d+).*(title="([^"]+)")?/', $item['options'], $matches))
- {
- $item['popup'] = $matches[2].'x'.$matches[3];
- $item['onExecute'] = 'javaScript:nm_action';
- if (isset($matches[5])) $item['tooltip'] = $matches[5];
- unset($item['options']);
- }
- }
- if (empty($item['icon'])) $item['icon'] = $app.'/navbar';
- if (empty($item['group'])) $item['group'] = $group;
- if (empty($item['onExecute'])) $item['onExecute'] = 'javaScript:app.admin.group';
- if (!isset($item['allowOnMultiple'])) $item['allowOnMultiple'] = false;
- if (!isset($item['enableId'])) $item['enableId'] = '^/groups/-\\d+';
-
- $actions[$item['id']] = $item;
+ $action['enableId'] = '^/groups/-\\d+';
}
}
+
return $actions;
}
@@ -273,6 +219,90 @@ class admin_ui
return $actions;
}
+ /**
+ * Actions on groups
+ *
+ * @return array
+ */
+ public static function group_actions()
+ {
+ $user_actions = self::user_actions();
+ $actions = array(
+ 'view' => array(
+ 'onExecute' => 'javaScript:app.admin.group',
+ 'caption' => 'Show members',
+ 'default' => true,
+ 'group' => $group=1,
+ 'allowOnMultiple' => false
+ ),
+ 'add' => array(
+ 'group' => $group,
+ )+$user_actions['add'],
+ 'acl' => array(
+ 'onExecute' => 'javaScript:app.admin.group',
+ 'caption' => 'Access control',
+ 'url' => 'menuaction=admin.admin_acl.index&account_id=$id',
+ 'popup' => '900x450',
+ 'icon' => 'lock',
+ 'group' => 2,
+ 'allowOnMultiple' => false
+ ),
+ );
+ if (!$GLOBALS['egw']->acl->check('account_access',64,'admin')) // no rights to set ACL-rights
+ {
+ $actions['deny'] = array(
+ 'caption' => 'Deny access',
+ 'url' => 'menuaction=admin.admin_denyaccess.list_apps&account_id=$id',
+ 'onExecute' => 'javaScript:app.admin.group',
+ 'icon' => 'cancel',
+ 'group' => 2,
+ 'allowOnMultiple' => false
+ );
+ }
+
+ $group = 5; // allow to place actions in different groups by hook, this is the default
+
+ // supporting both old way using $GLOBALS['menuData'] and new just returning data in hook
+ $apps = array_unique(array_merge(array('admin'), Api\Hooks::implemented('edit_group')));
+ foreach($apps as $app)
+ {
+ $GLOBALS['menuData'] = $data = array();
+ $data = Api\Hooks::single('edit_group', $app);
+ if (!is_array($data)) $data = $GLOBALS['menuData'];
+
+ foreach($data as $item)
+ {
+ // allow hook to return "real" actions, but still support legacy: description, url, extradata, options
+ if (empty($item['caption']))
+ {
+ $item['caption'] = $item['description'];
+ unset($item['description']);
+ }
+ if (isset($item['url']) && isset($item['extradata']))
+ {
+ $item['url'] = $item['extradata'].'&account_id=$id';
+ $item['id'] = substr($item['extradata'], 11);
+ unset($item['extradata']);
+ $matches = null;
+ if ($item['options'] && preg_match('/(egw_openWindowCentered2?|window.open)\([^)]+,(\d+),(\d+).*(title="([^"]+)")?/', $item['options'], $matches))
+ {
+ $item['popup'] = $matches[2].'x'.$matches[3];
+ $item['onExecute'] = 'javaScript:nm_action';
+ if (isset($matches[5])) $item['tooltip'] = $matches[5];
+ unset($item['options']);
+ }
+ }
+ if (empty($item['icon'])) $item['icon'] = $app.'/navbar';
+ if (empty($item['group'])) $item['group'] = $group;
+ if (empty($item['onExecute'])) $item['onExecute'] = 'javaScript:app.admin.group';
+ if (!isset($item['allowOnMultiple'])) $item['allowOnMultiple'] = false;
+
+ $actions[$item['id']] = $item;
+ }
+ }
+ return $actions;
+ }
+
/**
* Callback for nextmatch to fetch users
*
@@ -318,6 +348,49 @@ class admin_ui
return self::$accounts->total;
}
+ /**
+ * Callback for the nextmatch to get groups
+ */
+ public static function get_groups(&$query, &$rows)
+ {
+ $groups = $GLOBALS['egw']->accounts->search(array(
+ 'type' => 'groups',
+ 'order' => $query['order'],
+ 'sort' => $query['sort'],
+ 'start' => (int)$query['start'],
+ 'num_rows' => (int)$query['num_rows']
+ ));
+
+ $apps = array();
+ foreach($GLOBALS['egw_info']['apps'] as $app => $data)
+ {
+ if (!$data['enabled'] || !$data['status'] || $data['status'] == 3)
+ {
+ continue; // do NOT show disabled apps, or our API (status = 3)
+ }
+
+ $apps[] = $app;
+ }
+
+ $rows = array();
+ foreach($groups as &$group)
+ {
+ $run_rights = $GLOBALS['egw']->acl->get_user_applications($group['account_id'], false, false);
+ foreach($apps as $app)
+ {
+ if((boolean)$run_rights[$app])
+ {
+ $group['apps'][] = $app;
+ }
+ }
+
+ $group['members'] = $GLOBALS['egw']->accounts->members($group['account_id'],true);
+ $rows[] = $group;
+ }
+
+ return $GLOBALS['egw']->accounts->total;
+ }
+
/**
* Autoload tree from $_GET['id'] on
*/
diff --git a/admin/js/app.js b/admin/js/app.js
index c0b8f8c4c8..0c143e7f16 100644
--- a/admin/js/app.js
+++ b/admin/js/app.js
@@ -89,6 +89,8 @@ app.classes.admin = AppJS.extend(
case 'admin.index':
var iframe = this.iframe = this.et2.getWidgetById('iframe');
this.nm = this.et2.getWidgetById('nm');
+ this.groups = this.et2.getWidgetById('groups');
+ this.groups.set_disabled(true);
this.ajax_target = this.et2.getWidgetById('ajax_target');
if (iframe)
{
@@ -176,6 +178,7 @@ app.classes.admin = AppJS.extend(
}
this.iframe.set_disabled(!_url || ajax);
this.nm.set_disabled(!!_url || ajax);
+ this.groups.set_disabled(true);
this.ajax_target.set_disabled(!ajax);
},
@@ -343,12 +346,20 @@ app.classes.admin = AppJS.extend(
{
var link = _widget.getUserData(_id, 'link');
+ this.groups.set_disabled(true);
+ this.nm.set_disabled(false);
+
if (_id == '/accounts' || _id.substr(0, 8) == '/groups/')
{
this.load();
var parts = _id.split('/');
this.et2.getWidgetById('nm').applyFilters({ filter: parts[2] ? parts[2] : '', search: ''});
}
+ else if (_id === '/groups')
+ {
+ this.load();
+ this.group_list();
+ }
else if (typeof link == 'undefined')
{
_widget.openItem(_id, 'toggle');
@@ -364,6 +375,16 @@ app.classes.admin = AppJS.extend(
}
},
+ /**
+ * Show the group list in the main window
+ */
+ group_list: function group_list()
+ {
+ this.nm.set_disabled(true);
+ this.groups.set_disabled(false);
+ },
+
+
/**
* View, edit or delete a group callback for tree
*
@@ -372,14 +393,17 @@ app.classes.admin = AppJS.extend(
*/
group: function(_action, _senders)
{
+ // Tree IDs look like /groups/ID, nm uses admin::ID
+ var from_nm = _senders[0].id.indexOf('::') > 0;
+ var account_id = _senders[0].id.split(from_nm ? '::' : '/')[from_nm ? 1 : 2];
+
switch(_action.id)
{
case 'view':
- this.run(_senders[0].id, this.et2.getWidgetById('tree'));
+ this.run(from_nm ? '/groups/'+account_id : _senders[0].id, this.et2.getWidgetById('tree'));
break;
case 'delete':
- var account_id = _senders[0].id.split('/')[2];
this.egw.json('admin_account::ajax_delete_group', [account_id]).sendRequest();
break;
@@ -389,14 +413,14 @@ app.classes.admin = AppJS.extend(
alert('Missing url in action '+_action.id+'!');
break;
}
- var url = _action.data.url.replace('$id', _senders[0].id.split('/')[2]);
+ var url = unescape(_action.data.url).replace('$id', account_id);
if (url[0] != '/' && url.substr(0, 4) != 'http')
{
url = this.egw.link('/index.php', url);
}
- if (_action.data.popup)
+ if (_action.data.popup || _action.data.width && _action.data.height)
{
- this.egw.open_link(url, '_blank', _action.data.popup);
+ this.egw.open_link(url, '_blank', _action.data.popup ? _action.data.popup : _action.data.width + 'x' + _action.data.height);
}
else
{
diff --git a/admin/templates/default/app.css b/admin/templates/default/app.css
index 6da1b94948..4cf05f5a97 100644
--- a/admin/templates/default/app.css
+++ b/admin/templates/default/app.css
@@ -26,6 +26,12 @@ body {
background-color: white;
}
+/** Group list */
+#admin-index_groups div.innerContainer {
+ overflow: auto;
+ max-height: 7em;
+}
+
tr.adminAccountInactive .adminStatus {
color: red;
}
diff --git a/admin/templates/default/index.xet b/admin/templates/default/index.xet
index 821ab69d44..4c6efb3d75 100644
--- a/admin/templates/default/index.xet
+++ b/admin/templates/default/index.xet
@@ -46,9 +46,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/admin/templates/pixelegg/app.css b/admin/templates/pixelegg/app.css
index 292bdd2641..8085e10c44 100755
--- a/admin/templates/pixelegg/app.css
+++ b/admin/templates/pixelegg/app.css
@@ -36,6 +36,11 @@ body {
#admin_iframe {
background-color: white;
}
+/** Group list */
+#admin-index_groups div.innerContainer {
+ overflow: auto;
+ max-height: 5em;
+}
tr.adminAccountInactive .adminStatus {
color: red;
}