Commit 2f74756ac73867d476509a5b60384467616f6da3

Authored by Bryn Divey
1 parent a791ff7a

Fixes from 24/05/2006


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@5425 c91229c3-7414-0410-bfa2-8a42b809f60b
config/config.ini
@@ -179,6 +179,10 @@ passwordLength = 6 @@ -179,6 +179,10 @@ passwordLength = 6
179 ; default is set to "false" meaning that admins can create users with shorter passwords. 179 ; default is set to "false" meaning that admins can create users with shorter passwords.
180 restrictAdminPasswords = default 180 restrictAdminPasswords = default
181 181
  182 +; restrict users from accessing their preferences menus?
  183 +restrictPreferences = true
  184 +
  185 +
182 ; This is configuration for the built-in authentication provider 186 ; This is configuration for the built-in authentication provider
183 [builtinauth] 187 [builtinauth]
184 ; 188 ;
lib/templating/kt3template.inc.php
@@ -268,7 +268,9 @@ class KTPage { @@ -268,7 +268,9 @@ class KTPage {
268 268
269 /* final render call. */ 269 /* final render call. */
270 function render() { 270 function render() {
271 - global $default; 271 + global $default;
  272 + $oConfig = KTConfig::getSingleton();
  273 +
272 if (empty($this->contents)) { 274 if (empty($this->contents)) {
273 $this->contents = ""; 275 $this->contents = "";
274 } 276 }
@@ -278,63 +280,60 @@ class KTPage { @@ -278,63 +280,60 @@ class KTPage {
278 $this->contents = ""; 280 $this->contents = "";
279 } 281 }
280 282
281 - if (!is_string($this->contents)) {  
282 - $this->contents = $this->contents->render();  
283 - }  
284 -  
285 - // if we have no portlets, make the ui a tad nicer.  
286 - if (empty($this->portlets)) {  
287 - $this->show_portlets = false;  
288 - } 283 + if (!is_string($this->contents)) {
  284 + $this->contents = $this->contents->render();
  285 + }
289 286
290 - if (empty($this->title)) {  
291 - if (!empty($this->breadcrumbDetails)) {  
292 - $this->title = $this->breadcrumbDetails;  
293 - } else if (!empty($this->breadcrumbs)) {  
294 - $this->title = array_slice($this->breadcrumbs, -1);  
295 - $this->title = $this->title[0]['label'];  
296 - } else if (!empty($this->breadcrumbSection)) {  
297 - $this->title = $this->breadcrumbSection['label'];  
298 - } else {  
299 - $this->title = $this->componentLabel;  
300 - }  
301 - } 287 + // if we have no portlets, make the ui a tad nicer.
  288 + if (empty($this->portlets)) {
  289 + $this->show_portlets = false;
  290 + }
302 291
303 - $this->userMenu = array();  
304 - if (!(PEAR::isError($this->user) || is_null($this->user) || $this->user->isAnonymous())) {  
305 - $this->userMenu = array(  
306 - "preferences" => $this->_actionHelper(array("name" => _kt("Preferences"), "action" => "preferences", "active" => 0)),  
307 - "logout" => $this->_actionHelper(array("name" => _kt("Logout"), "action" => "logout", "active" => 0)),  
308 - );  
309 - } else {  
310 - $this->userMenu = array(  
311 - "login" => $this->_actionHelper(array("name" => _kt("Login"), "action" => "login")),  
312 - );  
313 - } 292 + if (empty($this->title)) {
  293 + if (!empty($this->breadcrumbDetails)) {
  294 + $this->title = $this->breadcrumbDetails;
  295 + } else if (!empty($this->breadcrumbs)) {
  296 + $this->title = array_slice($this->breadcrumbs, -1);
  297 + $this->title = $this->title[0]['label'];
  298 + } else if (!empty($this->breadcrumbSection)) {
  299 + $this->title = $this->breadcrumbSection['label'];
  300 + } else {
  301 + $this->title = $this->componentLabel;
  302 + }
  303 + }
314 304
315 - // FIXME we need a more complete solution to navigation restriction  
316 - if (!is_null($this->menu['administration']) && !is_null($this->user)) {  
317 - if (!Permission::userIsSystemAdministrator($this->user->getId())) {  
318 - unset($this->menu['administration']);  
319 - }  
320 - } 305 + $this->userMenu = array();
  306 + if (!(PEAR::isError($this->user) || is_null($this->user) || $this->user->isAnonymous())) {
  307 + if ($oConfig->get("user_prefs/restrictPreferences", false) && !Permission::userIsSystemAdministrator($this->user->getId())) {
  308 + $this->userMenu = array("logout" => $this->_actionHelper(array("name" => _kt("Logout"), "action" => "logout", "active" => 0)),);
  309 + } else {
  310 + $this->userMenu = array("preferences" => $this->_actionHelper(array("name" => _kt("Preferences"), "action" => "preferences", "active" => 0)),
  311 + "logout" => $this->_actionHelper(array("name" => _kt("Logout"), "action" => "logout", "active" => 0)),);
  312 + }
  313 + } else {
  314 + $this->userMenu = array("login" => $this->_actionHelper(array("name" => _kt("Login"), "action" => "login")),);
  315 + }
321 316
322 - $sContentType = 'Content-type: ' . $this->contentType;  
323 - if(!empty($this->charset)) {  
324 - $sContentType .= '; charset=' . $this->charset;  
325 - }; 317 + // FIXME we need a more complete solution to navigation restriction
  318 + if (!is_null($this->menu['administration']) && !is_null($this->user)) {
  319 + if (!Permission::userIsSystemAdministrator($this->user->getId())) {
  320 + unset($this->menu['administration']);
  321 + }
  322 + }
  323 +
  324 + $sContentType = 'Content-type: ' . $this->contentType;
  325 + if(!empty($this->charset)) {
  326 + $sContentType .= '; charset=' . $this->charset;
  327 + };
326 328
327 329
328 - header($sContentType); 330 + header($sContentType);
329 331
330 $oTemplating =& KTTemplating::getSingleton(); 332 $oTemplating =& KTTemplating::getSingleton();
331 $oTemplate = $oTemplating->loadTemplate($this->template); 333 $oTemplate = $oTemplating->loadTemplate($this->template);
332 - $aTemplateData = array(  
333 - "page" => $this,  
334 - "systemversion" => $default->systemVersion,  
335 - "versionname" => $default->versionName,  
336 - );  
337 - $oConfig = KTConfig::getSingleton(); 334 + $aTemplateData = array("page" => $this,
  335 + "systemversion" => $default->systemVersion,
  336 + "versionname" => $default->versionName,);
338 if ($oConfig->get("ui/automaticRefresh", false)) { 337 if ($oConfig->get("ui/automaticRefresh", false)) {
339 $aTemplateData['refreshTimeout'] = (int)$oConfig->get("session/sessionTimeout") + 3; 338 $aTemplateData['refreshTimeout'] = (int)$oConfig->get("session/sessionTimeout") + 3;
340 } 339 }
@@ -342,7 +341,7 @@ class KTPage { @@ -342,7 +341,7 @@ class KTPage {
342 // unlike the rest of KT, we use echo here. 341 // unlike the rest of KT, we use echo here.
343 echo $oTemplate->render($aTemplateData); 342 echo $oTemplate->render($aTemplateData);
344 } 343 }
345 - 344 +
346 345
347 /** heler functions */ 346 /** heler functions */
348 // returns an array ("url", "label") 347 // returns an array ("url", "label")
plugins/ktcore/admin/userManagement.php
@@ -75,13 +75,17 @@ var $sHelpPage = 'ktcore/admin/manage users.html'; @@ -75,13 +75,17 @@ var $sHelpPage = 'ktcore/admin/manage users.html';
75 $no_search = false; 75 $no_search = false;
76 } 76 }
77 77
  78 +
  79 + $aAuthenticationSources =& KTAuthenticationSource::getList();
  80 +
78 $oTemplating =& KTTemplating::getSingleton(); 81 $oTemplating =& KTTemplating::getSingleton();
79 $oTemplate = $oTemplating->loadTemplate("ktcore/principals/useradmin"); 82 $oTemplate = $oTemplating->loadTemplate("ktcore/principals/useradmin");
80 $aTemplateData = array( 83 $aTemplateData = array(
81 "context" => $this, 84 "context" => $this,
82 "search_fields" => $search_fields, 85 "search_fields" => $search_fields,
83 "search_results" => $search_results, 86 "search_results" => $search_results,
84 - 'no_search' => $no_search, 87 + "no_search" => $no_search,
  88 + "authentication_sources" => $aAuthenticationSources,
85 ); 89 );
86 return $oTemplate->render($aTemplateData); 90 return $oTemplate->render($aTemplateData);
87 } 91 }
@@ -121,14 +125,11 @@ var $sHelpPage = 'ktcore/admin/manage users.html'; @@ -121,14 +125,11 @@ var $sHelpPage = 'ktcore/admin/manage users.html';
121 $add_fields[] = new KTStringWidget(_kt('Mobile Number'), _kt("The mobile phone number of the user. e.g. <strong>999 9999 999</strong>"), 'mobile_number', null, $this->oPage, false, null, null, $aOptions); 125 $add_fields[] = new KTStringWidget(_kt('Mobile Number'), _kt("The mobile phone number of the user. e.g. <strong>999 9999 999</strong>"), 'mobile_number', null, $this->oPage, false, null, null, $aOptions);
122 $add_fields[] = new KTStringWidget(_kt('Maximum Sessions'), _kt('As a safety precaution, it is useful to limit the number of times a given account can log in, before logging out. This prevents a single account being used by many different people.'), 'max_sessions', '3', $this->oPage, true, null, null, $aOptions); 126 $add_fields[] = new KTStringWidget(_kt('Maximum Sessions'), _kt('As a safety precaution, it is useful to limit the number of times a given account can log in, before logging out. This prevents a single account being used by many different people.'), 'max_sessions', '3', $this->oPage, true, null, null, $aOptions);
123 127
124 - $aAuthenticationSources =& KTAuthenticationSource::getList();  
125 -  
126 $oTemplating =& KTTemplating::getSingleton(); 128 $oTemplating =& KTTemplating::getSingleton();
127 $oTemplate = $oTemplating->loadTemplate("ktcore/principals/adduser"); 129 $oTemplate = $oTemplating->loadTemplate("ktcore/principals/adduser");
128 $aTemplateData = array( 130 $aTemplateData = array(
129 "context" => &$this, 131 "context" => &$this,
130 "add_fields" => $add_fields, 132 "add_fields" => $add_fields,
131 - "authentication_sources" => $aAuthenticationSources,  
132 ); 133 );
133 return $oTemplate->render($aTemplateData); 134 return $oTemplate->render($aTemplateData);
134 } 135 }
preferences.php
@@ -39,10 +39,15 @@ require_once(KT_LIB_DIR . &#39;/widgets/fieldWidgets.php&#39;); @@ -39,10 +39,15 @@ require_once(KT_LIB_DIR . &#39;/widgets/fieldWidgets.php&#39;);
39 class PreferencesDispatcher extends KTStandardDispatcher { 39 class PreferencesDispatcher extends KTStandardDispatcher {
40 var $sSection = 'preferences'; 40 var $sSection = 'preferences';
41 41
42 - function check() {  
43 - if ($this->oUser->getId() == -2) { return false; }  
44 - return parent::check();  
45 - } 42 + function check() {
  43 + $oConfig =& KTConfig::getSingleton();
  44 + if ($this->oUser->getId() == -2 ||
  45 + ($oConfig->get('user_prefs/restrictPreferences', false) && !Permission::userIsSystemAdministrator($this->oUser->getId()))) {
  46 + return false;
  47 + }
  48 +
  49 + return parent::check();
  50 + }
46 51
47 function PreferencesDispatcher() { 52 function PreferencesDispatcher() {
48 $this->aBreadcrumbs = array( 53 $this->aBreadcrumbs = array(
@@ -52,15 +57,15 @@ class PreferencesDispatcher extends KTStandardDispatcher { @@ -52,15 +57,15 @@ class PreferencesDispatcher extends KTStandardDispatcher {
52 } 57 }
53 58
54 function do_main() { 59 function do_main() {
55 - $this->oPage->setBreadcrumbDetails(_kt("Your Preferences"));  
56 - $this->oPage->title = _kt("Dashboard"); 60 + $this->oPage->setBreadcrumbDetails(_kt("Your Preferences"));
  61 + $this->oPage->title = _kt("Dashboard");
57 62
58 63
59 - $oUser =& $this->oUser; 64 + $oUser =& $this->oUser;
60 65
61 - $aOptions = array('autocomplete' => false); 66 + $aOptions = array('autocomplete' => false);
62 67
63 - $edit_fields = array(); 68 + $edit_fields = array();
64 $edit_fields[] = new KTStringWidget(_kt('Name'), _kt('Your full name. This is shown in reports and listings. e.g. <strong>John Smith</strong>'), 'name', $oUser->getName(), $this->oPage, true, null, null, $aOptions); 69 $edit_fields[] = new KTStringWidget(_kt('Name'), _kt('Your full name. This is shown in reports and listings. e.g. <strong>John Smith</strong>'), 'name', $oUser->getName(), $this->oPage, true, null, null, $aOptions);
65 $edit_fields[] = new KTStringWidget(_kt('Email Address'), _kt('Your email address. Notifications and alerts are mailed to this address if <strong>email notifications</strong> is set below. e.g. <strong>jsmith@acme.com</strong>'), 'email_address', $oUser->getEmail(), $this->oPage, false, null, null, $aOptions); 70 $edit_fields[] = new KTStringWidget(_kt('Email Address'), _kt('Your email address. Notifications and alerts are mailed to this address if <strong>email notifications</strong> is set below. e.g. <strong>jsmith@acme.com</strong>'), 'email_address', $oUser->getEmail(), $this->oPage, false, null, null, $aOptions);
66 $edit_fields[] = new KTCheckboxWidget(_kt('Email Notifications'), _kt('If this is specified then the you will receive certain notifications. If it is not set, then you will only see notifications on the <strong>Dashboard</strong>'), 'email_notifications', $oUser->getEmailNotification(), $this->oPage, false, null, null, $aOptions); 71 $edit_fields[] = new KTCheckboxWidget(_kt('Email Notifications'), _kt('If this is specified then the you will receive certain notifications. If it is not set, then you will only see notifications on the <strong>Dashboard</strong>'), 'email_notifications', $oUser->getEmailNotification(), $this->oPage, false, null, null, $aOptions);
templates/kt3/standard_page.smarty
@@ -76,7 +76,7 @@ @@ -76,7 +76,7 @@
76 76
77 {foreach item=aMenuItem from=$page->userMenu name=prefmenu} 77 {foreach item=aMenuItem from=$page->userMenu name=prefmenu}
78 {if ($aMenuItem.active == 1)} 78 {if ($aMenuItem.active == 1)}
79 - <a href="{$aMenuItem.url}">{$aMenuItem.label}</a> 79 + <a style='border: 4px solid red;' href="{$aMenuItem.url}">{$aMenuItem.label}</a>
80 {else} 80 {else}
81 <a href="{$aMenuItem.url}">{$aMenuItem.label}</a> 81 <a href="{$aMenuItem.url}">{$aMenuItem.label}</a>
82 {/if} 82 {/if}
templates/ktcore/principals/adduser.smarty
1 <h2>{i18n}Add a user{/i18n}</h2> 1 <h2>{i18n}Add a user{/i18n}</h2>
2 2
3 -<p class="descriptiveText">{i18n}Please complete the form below to add a new user. Fields marked with a red square are required. By default, users are created using KnowledgeTree's builtin authentication provider. Should you wish to use an external authentication provider such as LDAP, please ensure that the provider's plugin is registered and enabled.{/i18n}</p>  
4 -  
5 -{if $authentication_sources}  
6 - <form action="{$smarty.server.PHP_SELF}" method="POST">  
7 - <input type="hidden" name="action" value="addUserFromSource" />  
8 - <fieldset><legend>{i18n}Add a user from an authentication source{/i18n}</legend>  
9 -  
10 -<p class="descriptiveText">{i18n}Instead of manually creating the user within  
11 -the document management system, the user can be found within an  
12 -authentication source (such as an LDAP directory) that has already been  
13 -configured. This ensures that the user is correctly set up with limited  
14 -intervention from the administrator, and that the user will not need to  
15 -remember an additional password for the document management  
16 -system.{/i18n}</p>  
17 -  
18 - {entity_select name="source_id" entities=$authentication_sources}  
19 - <div class="form_actions ">  
20 - <input type="submit" name="submit" value="{i18n}Add from source{/i18n}" />  
21 - </div>  
22 - </fieldset>  
23 - </form>  
24 -</p>  
25 -  
26 -<p class="descriptiveText">{i18n}Alternatively, you can manually create a user  
27 -within KnowledgeTree below.{/i18n}</p>  
28 -{/if} 3 +<p class="descriptiveText">{i18n}Please complete the form below to add
  4 +a new user. Fields marked with a red square are required. By default,
  5 +users are created using KnowledgeTree's builtin authentication
  6 +provider. Should you wish to use an external authentication provider
  7 +such as LDAP, please ensure that the provider's plugin is registered
  8 +and use the form on the User Management page.{/i18n}</p>
29 9
30 <form action="{$smarty.server.PHP_SELF}" method="POST"> 10 <form action="{$smarty.server.PHP_SELF}" method="POST">
31 <input type="hidden" name="action" value="createUser" /> 11 <input type="hidden" name="action" value="createUser" />
templates/ktcore/principals/useradmin.smarty
1 <h2>{i18n}User Management{/i18n}</h2> 1 <h2>{i18n}User Management{/i18n}</h2>
2 2
3 3
4 -<!-- FIXME inline CSS is _very_ bad. -->  
5 -<fieldset>  
6 -<legend>{i18n}Add New Users{/i18n}</legend>  
7 -<p class="descriptiveText">{i18n}To allow users access to the DMS, you need to provide them with  
8 -credentials through this section. Even if you are using an external source  
9 -of login information like <strong>LDAP</strong>, you will need to use this section  
10 -to retrieve their information from the external source.{/i18n}</p>  
11 -<p><a href="{addQS}action=addUser{/addQS}" class="ktAction ktAddUser" style="float:  
12 -left; padding-right: 0.5em;">{i18n}Add a new user{/i18n}</a><a  
13 -href="{addQS}action=addUser{/addQS}">{i18n}Add a new user{/i18n}</a></p> 4 +
  5 +<fieldset> <legend>{i18n}Add new users{/i18n}</legend> <p
  6 +class="descriptiveText">{i18n}To add users to the DMS authentication
  7 +provider, you need to provide them with credentials through this
  8 +section. If you are using an external source of login information
  9 +like <strong>LDAP</strong>, ensure the appropriate plugin is loaded
  10 +and use the section below.{/i18n}</p> <p><a
  11 +href="{addQS}action=addUser{/addQS}" class="ktAction ktAddUser"
  12 +style="float: left; padding-right: 0.5em;">{i18n}Add a new
  13 +user{/i18n}</a><a href="{addQS}action=addUser{/addQS}">{i18n}Add a new
  14 +user{/i18n}</a></p>
  15 +
  16 +
14 </fieldset> 17 </fieldset>
  18 +{if $authentication_sources}
  19 + <form action="{$smarty.server.PHP_SELF}" method="POST">
  20 + <input type="hidden" name="action" value="addUserFromSource" />
  21 + <fieldset><legend>{i18n}Add a user from an authentication source{/i18n}</legend>
  22 +
  23 +<p class="descriptiveText">{i18n}Instead of manually creating the user within
  24 +the document management system, the user can be found within an
  25 +authentication source (such as an LDAP directory) that has already been
  26 +configured. This ensures that the user is correctly set up with limited
  27 +intervention from the administrator, and that the user will not need to
  28 +remember an additional password for the document management
  29 +system.{/i18n}</p>
  30 +
  31 + {entity_select name="source_id" entities=$authentication_sources}
  32 + <div class="form_actions ">
  33 + <input type="submit" name="submit" value="{i18n}Add from source{/i18n}" />
  34 + </div>
  35 + </fieldset>
  36 + </form>
  37 +</p>
  38 +{/if}
  39 +
15 40
16 <!-- we roll both in here. --> 41 <!-- we roll both in here. -->
17 <form action="{$smarty.server.PHP_SELF}" method="POST"> 42 <form action="{$smarty.server.PHP_SELF}" method="POST">
templates/ktstandard/action/email.smarty
@@ -44,21 +44,73 @@ addLoadEvent(kt_email_onload); @@ -44,21 +44,73 @@ addLoadEvent(kt_email_onload);
44 <input type="hidden" name="fDocumentId" value="{$context->oDocument->getId()}" /> 44 <input type="hidden" name="fDocumentId" value="{$context->oDocument->getId()}" />
45 45
46 <table> 46 <table>
47 -<tr><td valign="top" colspan="3"><strong>{i18n}Groups{/i18n}</strong></td></tr><tr><td valign="top" width=1%> 47 +<tr>
  48 + <td valign="top" colspan="3"><strong>{i18n}Groups{/i18n}</strong></td>
  49 +</tr>
  50 +<tr>
  51 + <td valign="top" width="1%">
48 52
49 -<select name="groupSelect" size="4" multiple>  
50 -{foreach from=$groups item=oGroup}  
51 -<OPTION value="{$oGroup->getId()}" onDblClick="optGroup.transferRight()" >{$oGroup->getName()}</OPTION>  
52 -{/foreach}  
53 -</select></td><td width=1%><input TYPE="button" NAME="right" VALUE="&gt;&gt;" ONCLICK="optGroup.transferRight()"><input TYPE="button" NAME="left" VALUE="&lt;&lt;" ONCLICK="optGroup.transferLeft()"></td><td><select name="chosenGroups" size="5" multiple><option>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</option></select></td></tr> 53 + <select name="groupSelect" size="4" multiple>
  54 + {foreach from=$groups item=oGroup}
  55 + <option value="{$oGroup->getId()}" onDblClick="optGroup.transferRight()" >{$oGroup->getName()}</option>
  56 + {/foreach}
  57 + </select>
  58 + </td>
54 59
55 -<tr><td colspan="3"><strong>{i18n}Users{/i18n}</strong></td><tr>  
56 -<tr><td><select name="userSelect" size="4" multiple>  
57 -{foreach from=$users item=oUser}  
58 -<OPTION value="{$oUser->getId()}" onDblClick="optUser.transferRight()">  
59 -{$oUser->getName()}</OPTION>  
60 -{/foreach}  
61 -</select></td><td><input TYPE="button" NAME="right" VALUE="&gt;&gt;" ONCLICK="optUser.transferRight()"><input TYPE="button" NAME="left" VALUE="&lt;&lt;" ONCLICK="optUser.transferLeft()"></td><td width="30%"><select name="chosenUsers" size="5" multiple><option>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</option></select></td></tr> 60 + <td align="center">
  61 + <input name="right" style="width: 60px;" value="&raquo;" onclick="optGroup.transferRight()" type="button"><br /><br />
  62 + <input name="left" style="width: 60px;" value="&laquo;" onclick="optGroup.transferLeft()" type="button">
  63 + </td>
  64 +
  65 +
  66 + <td valign="top" width="1%">
  67 + <select name="chosenGroups" size="5" multiple="multiple">
  68 + </select>
  69 + </td>
  70 +</tr>
  71 +
  72 +<tr>
  73 + <td><label for="ug-filter">{i18n}Filter{/i18n}</label>
  74 + <input name="filterUG" id="ug-filter" onkeyup="optGroup.sortSelectMatch(groupSelect, this.value)" onchange="optGroup.sortSelectMatch(groupSelect, this.value)" type="text">
  75 + </td>
  76 + <td>&nbsp;</td>
  77 + <td><label for="og-filter">{i18n}Filter{/i18n}</label>
  78 + <input name="filterOG" id="og-filter" onkeyup="optGroup.sortSelectMatch(chosenGroups, this.value)" onchange="optGroup.sortSelectMatch(chosenGroups, this.value)" type="text">
  79 + </td>
  80 + </tr>
  81 +
  82 +<tr>
  83 + <td colspan="3"><strong>{i18n}Users{/i18n}</strong></td>
  84 +</tr>
  85 +<tr>
  86 + <td valign="top" width="1%">
  87 + <select name="userSelect" size="10" multiple="multiple">
  88 + {foreach from=$users item=oUser}
  89 + <option value="{$oUser->getId()}" onDblClick="optUser.transferRight()">{$oUser->getName()}</option>
  90 + {/foreach}
  91 + </select>
  92 + </td>
  93 +
  94 + <td align="center">
  95 + <input name="right" style="width: 60px;" value="&raquo;" onclick="optUser.transferRight()" type="button"><br /><br />
  96 + <input name="left" style="width: 60px;" value="&laquo;" onclick="optUser.transferLeft()" type="button">
  97 + </td>
  98 +
  99 + <td valign="top" width="1%">
  100 + <select name="chosenUsers" size="10" multiple="multiple">
  101 + </select>
  102 + </td>
  103 +</tr>
  104 +<tr>
  105 + <td><label for="uu-filter">{i18n}Filter{/i18n}</label>
  106 + <input name="filterUU" id="uu-filter" onkeyup="optUser.sortSelectMatch(userSelect, this.value)" onchange="optUser.sortSelectMatch(userSelect, this.value)" type="text">
  107 + </td>
  108 + <td>&nbsp;</td>
  109 + <td><label for="ou-filter">{i18n}Filter{/i18n}</label>
  110 + <input name="filterOU" id="ou-filter" onkeyup="optUser.sortSelectMatch(chosenUsers, this.value)" onchange="optUser.sortSelectMatch(chosenUsers, this.value)" type="text">
  111 + </td>
  112 + </tr>
  113 +
62 114
63 </table> 115 </table>
64 116