a few more steps towards a new admin

This commit is contained in:
Ralf Becker 2013-07-03 16:27:18 +00:00
parent 76ab4eee25
commit b2f733c4d5
6 changed files with 279 additions and 11 deletions

View File

@ -25,6 +25,13 @@ class admin_ui
'index' => true,
);
/**
* Reference to global accounts object
*
* @var accounts
*/
private static $accounts;
/**
* New index page
*
@ -36,11 +43,156 @@ class admin_ui
$tpl = new etemplate_new('admin.index');
$content = array();
$content['admin_nm'] = array(
'get_rows' => 'admin_ui::get_users',
'no_cat' => true,
'no_filter2' => true,
'filter_label' => 'Group',
'filter_no_lang' => true,
'lettersearch' => true,
'order' => 'account_lid',
'sort' => 'ASC',
'row_id' => 'account_id',
'default_cols' => '!account_id,account_created',
'actions' => self::user_actions(),
);
//$content['msg'] = 'Hi Ralf ;-)';
$sel_options['tree'] = $this->tree_data();
$sel_options['filter'] = array('' => lang('All'));
foreach(self::$accounts->search(array(
'type' => 'groups',
'start' => false,
'order' => 'account_lid',
'sort' => 'ASC',
)) as $account_id => $data)
{
$sel_options['filter'][$data['account_id']] = empty($data['account_description']) ? $data['account_lid'] : array(
'label' => $data['account_lid'],
'title' => $data['account_description'],
);
}
$sel_options['account_primary_group'] = $sel_options['filter'];
unset($sel_options['account_primary_group']['']);
$tpl->exec('admin.admin_ui.index', $content, $sel_options);
}
/**
* Actions on users
*
* @return array
*/
public static function user_actions()
{
$actions = array(
'edit' => array(
'caption' => 'Open',
'default' => true,
'allowOnMultiple' => false,
'url' => 'menuaction=admin.uiaccounts.edit_user&account_id=$id',
'group' => $group=0,
'onExecute' => 'javaScript:app.admin.iframe_location',
),
'view' => array(
'caption' => 'View',
'allowOnMultiple' => false,
'url' => 'menuaction=admin.uiaccounts.view_user&account_id=$id',
'group' => $group,
'onExecute' => 'javaScript:app.admin.iframe_location',
),
);
++$group;
// supporting both old way using $GLOBALS['menuData'] and new just returning data in hook
$apps = array_unique(array_merge(array('admin'), $GLOBALS['egw']->hooks->hook_implemented('edit_user')));
foreach($apps as $n => $app)
{
if ($app == 'felamimail') continue; // disabled fmail for now, as it break whole admin, dono why
$GLOBALS['menuData'] = $data = array();
$data = $GLOBALS['egw']->hooks->single('edit_user', $app, true);
if (!$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']);
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.iframe_location';
$actions[$item['id']] = $item;
}
}
$actions['delete'] = array(
'caption' => 'Delete',
'group' => ++$group,
'url' => 'menuaction=admin.uiaccounts.delete_user&account_id=$id',
'onExecute' => 'javaScript:app.admin.iframe_location',
);
//error_log(__METHOD__."() actions=".array2string($actions));
return $actions;
}
/**
* Callback for nextmatch to fetch users
*
* @param array $query
* @param array &$rows=null
* @return int total number of rows available
*/
public static function get_users(array $query, array &$rows=null)
{
$params = array(
'type' => (int)$query['filter'] ? (int)$query['filter'] : 'accounts',
'start' => $query['start'],
'offset' => $query['num_rows'],
'order' => $query['order'],
'sort' => $query['sort'],
'active' => false,
);
if ($query['searchletter'])
{
$params['query'] = $query['searchletter'];
$params['query_type'] = 'start';
}
elseif($query['search'])
{
$params['query'] = $query['search'];
$params['query_type'] = 'all';
}
$rows = self::$accounts->search($params);
error_log(__METHOD__."() accounts->search(".array2string($params).") total=".self::$accounts->total);
foreach($rows as &$row)
{
$row['status'] = self::$accounts->is_expired($row) ?
lang('Expired').' '.egw_time::to($row['account_expires'], true) :
(!self::$accounts->is_active($row) ? lang('Disabled') :
($row['account_expires'] != -1 ? lang('Expires').' '.egw_time::to($row['account_expires'], true) :
lang('Enabled')));
if (!self::$accounts->is_active($row)) $row['status_class'] = 'adminAccountInactive';
}
return self::$accounts->total;
}
/**
* Autoload tree from $_GET['id'] on
*/
@ -144,6 +296,8 @@ class admin_ui
{
foreach($GLOBALS['egw']->accounts->search(array(
'type' => 'groups',
'order' => 'account_lid',
'sort' => 'ASC',
)) as $group)
{
$tree['item'][] = self::fix_userdata(array(
@ -183,7 +337,12 @@ class admin_ui
return $data;
}
private static function strip_item_keys(&$items)
/**
* Attribute 'item' has to be an array
*
* @param array $items
*/
private static function strip_item_keys(array &$items)
{
$items = array_values($items);
foreach($items as &$item)
@ -211,4 +370,13 @@ class admin_ui
}
return array_merge($GLOBALS['egw']->hooks->process('admin', array('admin')), self::$hook_data);
}
/**
* Init static variables
*/
public static function init_static()
{
self::$accounts = $GLOBALS['egw']->accounts;
}
}
admin_ui::init_static();

View File

@ -21,6 +21,15 @@ app.admin = AppJS.extend(
* et2 widget container
*/
et2: null,
/**
* reference to splitter
*/
splitter: null,
/**
* reference to splitter
*/
iframe: null,
/**
* Constructor
@ -57,8 +66,30 @@ app.admin = AppJS.extend(
this.et2 = _et2.widgetContainer;
var iframe = this.et2.getWidgetById('admin_iframe');
var iframe = this.iframe = this.et2.getWidgetById('admin_iframe');
if (iframe) iframe.set_src(egw.webserverUrl+'/admin/index.php');
var splitter = this.splitter = this.et2.getWidgetById('admin_splitter');
if (splitter)
{
window.setTimeout(function(){
splitter.dock();
}, 1);
}
},
/**
* Set location of iframe for given _action and _sender (row)
*
* @param _action
* @param _senders
*/
iframe_location: function(_action, _senders)
{
var id = _senders[0].id.split('::');
var url = _action.data.url.replace(/(%24|\$)id/, id[1]);
this.iframe.set_src(url);
},
/**
@ -70,15 +101,21 @@ app.admin = AppJS.extend(
run: function(_id, _widget)
{
var link = _widget.getUserData(_id, 'link');
var iframe = this.et2.getWidgetById('admin_iframe');
if (typeof link == 'undefined')
if (_id == '/accounts' || _id.substr(0, 8) == '/groups/')
{
this.splitter.undock();
var parts = _id.split('/');
this.et2.getWidgetById('admin_nm').applyFilters({ filter: parts[2] ? parts[2] : '', search: ''});
}
else if (typeof link == 'undefined')
{
_widget.openItem(_id, 'toggle');
}
else if (link[0] == '/' || link.substr(0,4) == 'http')
{
iframe.set_src(link+'&nonavbar=1');
this.splitter.dock();
this.iframe.set_src(link+'&nonavbar=1');
}
else if (link.substr(0,11) == 'javascript:')
{

View File

@ -282,7 +282,8 @@ error setting timer, wrong syntax or maybe there's one already running !!! admin
error! no appname found admin de Fehler: Kein Anwendungsname gefunden
error: %1 not found or other error !!! admin de Fehler: %1 nicht gefunden oder anderer Fehler!
exists admin de existiert
expires admin de abgelaufen
expired admin de abgelaufen
expires admin de läuft ab
explanation of ldapman admin de Dieses Modul ist derzeit nur für folgende Konfiguration getestet: Postfix, LDAP, Courier-Imap, Procmail und erfordert die Schemas: core und qmail(OID 7914). Weitere Konfigurationshinweise sind im README.ldapman im DOC Verzeichnis des Moduls ADMIN zu finden.
exports groups into a csv file. admin de Benutzergruppen in eine CSV-Datei exportieren.
exports users into a csv file. admin de Benutzer in eine CSV-Datei exportieren.

View File

@ -283,6 +283,7 @@ error setting timer, wrong syntax or maybe there's one already running !!! admin
error! no appname found admin en Error: No app name found!
error: %1 not found or other error !!! admin en Error: %1 not found or other error!
exists admin en Exists
expired admin en Expired
expires admin en Expires
explanation of ldapman admin en This module has been tested so far for POSTFIX, LDAP, Courier-IMAP and need the schemas CORE and QMAIL (OID7914). More details about using and configuring this system can be found in README.ldapman in the doc folder of ADMIN.
exports groups into a csv file. admin en Exports groups into a CSV file.

View File

@ -19,3 +19,20 @@ div#divAppbox {
body {
background-image: none;
}
/* otherwise it is transparent */
#admin_iframe {
background-color: white;
}
tr.adminAccountInactive .adminStatus {
color: red;
}
.adminOverflowEllipsis {
width: 100%;
white-space: nowrap;
display: block;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@ -1,9 +1,53 @@
<?xml version="1.0"?>
<!-- $Id$ -->
<overlay>
<template id="admin.index" template="" lang="" group="0" version="1.9.001">
<tree autoloading="admin_ui::ajax_tree" id="admin_tree" onclick="app.admin.run(widget.event_args[0],widget);" parent_node="admin_tree_target"/>
<html id="msg"/>
<iframe frameborder="1" height="500px" id="admin_iframe" scrolling="auto" width="100%"/>
<template id="admin.index.rows" template="" lang="" group="0" version="1.9.001">
<grid width="100%">
<columns>
<column/>
<column width="30"/>
<column/>
<column/>
<column/>
<column/>
<column/>
<column/>
<column/>
</columns>
<rows>
<row>
<nextmatch-sortheader label="Login-ID" id="account_lid"/>
<nextmatch-sortheader label="ID" id="account_id"/>
<nextmatch-sortheader label="Firstname" id="account_firstname"/>
<nextmatch-sortheader label="Lastname" id="account_lastname"/>
<nextmatch-sortheader label="EMail" id="account_email"/>
<nextmatch-sortheader label="Primary group" id="account_primary_group"/>
<nextmatch-sortheader label="Expires" id="account_expires"/>
<nextmatch-sortheader label="Created" id="account_created"/>
<nextmatch-sortheader label="Last modified" id="account_modified"/>
</row>
<row class="$row_cont[status_class]">
<description id="${row}[account_lid]" no_lang="1"/>
<description id="${row}[account_id]" no_lang="1"/>
<description id="${row}[account_firstname]" no_lang="1"/>
<description id="${row}[account_lastname]" no_lang="1"/>
<url-email id="${row}[account_email]" readonly="true" class="adminOverflowEllipsis"/>
<menulist>
<menupopup id="${row}[account_primary_group]" no_lang="1" readonly="true"/>
</menulist>
<description id="${row}[status]" no_lang="1" class="adminStatus"/>
<date-time id="${row}[account_created]" readonly="true"/>
<date-time id="${row}[account_modified]" readonly="true"/>
</row>
</rows>
</grid>
</template>
</overlay>
<template id="admin.index" template="" lang="" group="0" version="1.9.001">
<tree autoloading="admin_ui::ajax_tree" id="admin_tree" onclick="app.admin.run(widget.event_args[0],widget);" parent_node="admin_tree_target" std_images="bullet"/>
<html id="msg"/>
<split dock_side="topDock" id="admin_splitter" orientation="h">
<nextmatch id="admin_nm" template="admin.index.rows"/>
<iframe frameborder="1" height="500px" id="admin_iframe" scrolling="auto" width="100%"/>
</split>
</template>
</overlay>