Commit bff3e898 authored by Richard Mansfield's avatar Richard Mansfield
Browse files

Add support for mass user actions to admin search (bug #801069)



Add a checkbox beside each user in admin user search, select all/none
links, and a button to submit all the selected users to the bulk user
actions page.  Checkboxes are reset on each new search query, but not
when changing the page or order of results.

Change-Id: If232021b232ec69dcd74d74c3d4d3c3b2248c870
Signed-off-by: default avatarRichard Mansfield <richard.mansfield@catalyst.net.nz>
parent bd0cd991
......@@ -31,6 +31,8 @@ function UserSearch() {
self.rewritePaging();
self.rewriteSorting();
self.rewriteSetLimit();
self.selectusers = {};
self.rewriteCheckboxes();
self.params = {};
}
......@@ -90,7 +92,9 @@ function UserSearch() {
if (children.length == 1) {
var href = getNodeAttribute(children[0], 'href');
self.params = parseQueryString(href.substring(href.indexOf('?')+1, href.length));
self.doSearch();
// Assume this is only changing the page or the order of results,
// so pass true here to avoid clearing the selected users.
self.doSearch(true);
}
}
......@@ -136,18 +140,54 @@ function UserSearch() {
e.stop();
}
this.doSearch = function() {
this.doSearch = function(saveselected) {
self.params.action = 'search';
sendjsonrequest('search.json.php', self.params, 'POST', function(data) {
$('results').innerHTML = data.data;
if (!saveselected) {
self.selectusers = {};
}
if ($('searchresults')) {
self.rewritePaging();
self.rewriteSorting();
self.rewriteCheckboxes();
self.rewriteSetLimit();
}
});
}
this.rewriteCheckboxes = function() {
forEach(getElementsByTagAndClassName('input', 'selectusers', 'searchresults'), function(i) {
connect(i, 'onclick', function() {
if (i.checked) {
self.selectusers[i.value] = 1;
}
else {
delete self.selectusers[i.value];
}
});
if (self.selectusers[i.value]) {
i.checked = true;
}
});
if ($('selectall')) {
connect('selectall', 'onclick', function(e) {
e.stop();
forEach(getElementsByTagAndClassName('input', 'selectusers', 'searchresults'), function(i) {
self.selectusers[i.value] = 1;
i.checked = true;
});
});
connect('selectnone', 'onclick', function(e) {
e.stop();
forEach(getElementsByTagAndClassName('input', 'selectusers', 'searchresults'), function(i) {
delete self.selectusers[i.value];
i.checked = false;
});
});
}
}
this.rewriteSetLimit = function() {
if ($('setlimit')) {
forEach(getElementsByTagAndClassName('a', null, 'setlimit'), function(i) {
......@@ -158,7 +198,7 @@ function UserSearch() {
}
self.params.limit = scrapeText(i);
self.params.offset = Math.floor(self.params.offset / self.params.limit) * self.params.limit;
self.doSearch();
self.doSearch(true);
});
});
}
......@@ -168,3 +208,37 @@ function UserSearch() {
}
userSearch = new UserSearch();
addLoadEvent(function() {
forEach(getElementsByTagAndClassName('input', 'button', 'bulkactions'), function(input) {
connect(input, 'onclick', function() {
// Some of the selected users aren't on the page, so just add them all to the
// form now.
var count = 0;
if (userSearch.selectusers) {
for (j in userSearch.selectusers) {
appendChildNodes('bulkactions', INPUT({
'type': 'checkbox',
'name': 'users[' + j + ']',
'value': j,
'class': 'hidden',
'checked': 'checked'
}));
count++;
}
}
if (count) {
addElementClass('nousersselected', 'hidden');
appendChildNodes('bulkactions', INPUT({
'type': 'hidden',
'name': 'action',
'value': input.name,
}));
$('bulkactions').submit();
return false;
}
removeElementClass('nousersselected', 'hidden');
return false;
})
});
});
......@@ -751,6 +751,7 @@ $string['invitedby'] = 'Invited by';
$string['requestto'] = 'Request to';
$string['useradded'] = 'User added';
$string['invitationsent'] = 'Invitation sent';
$string['editselectedusers'] = 'Edit selected users';
// Bulk actions
$string['bulkactions'] = 'Bulk actions';
......
......@@ -275,12 +275,9 @@ function build_admin_user_search_results($search, $offset, $limit, $sortby, $sor
}
$searchurl = get_config('wwwroot') . 'admin/users/search.php?' . join('&', $params) . '&limit=' . $limit;
$usernametemplate = '<a href="' . get_config('wwwroot')
. '{if $USER->is_admin_for_user($r.id)}admin/users/edit.php?id={$r.id}{else}user/view.php?id={$r.id}{/if}">{$r.username}</a>';
$cols = array(
'icon' => array(
'template' => '<img src="{profile_icon_url user=$r maxwidth=40 maxheight=40}" alt="' . get_string('profileimage') . '" />',
'template' => 'admin/users/searchiconcolumn.tpl',
'class' => 'center',
),
'firstname' => array(
......@@ -294,7 +291,7 @@ function build_admin_user_search_results($search, $offset, $limit, $sortby, $sor
'username' => array(
'name' => get_string('username'),
'sort' => true,
'template' => $usernametemplate,
'template' => 'admin/users/searchusernamecolumn.tpl',
),
'email' => array(
'name' => get_string('email'),
......@@ -304,21 +301,19 @@ function build_admin_user_search_results($search, $offset, $limit, $sortby, $sor
$institutions = get_records_assoc('institution', '', '', '', 'name,displayname');
if (count($institutions) > 1) {
$template = '';
foreach ($THEME->inheritance as $themedir) {
$tpl = get_config('docroot') . 'theme/' . $themedir . '/templates/admin/users/searchinstitutioncolumn.tpl';
if (is_readable($tpl)) {
$template = file_get_contents($tpl);
break;
}
}
$cols['institution'] = array(
'name' => get_string('institution'),
'sort' => !get_config('usersallowedmultipleinstitutions'),
'template' => $template,
'template' => 'admin/users/searchinstitutioncolumn.tpl',
);
}
$cols['select'] = array(
'headhtml' => '<a href="" id="selectall">' . get_string('All') . '</a>&nbsp;<a href="" id="selectnone">' . get_string('none') . '</a>',
'template' => 'admin/users/searchselectcolumn.tpl',
'class' => 'center nojs-hidden-table-cell',
);
$smarty = smarty_core();
$smarty->assign_by_ref('results', $results);
$smarty->assign_by_ref('institutions', $institutions);
......
......@@ -38,3 +38,7 @@
display: table;
*display: block;
}
.nojs-hidden-table-cell {
display: table-cell;
*display: block;
}
......@@ -154,7 +154,7 @@ html>body .safe-hidden {
*margin: 0;
*padding: 0;
}
.nojs-hidden-inline, .nojs-hidden-block, .nojs-hidden-table {
.nojs-hidden-inline, .nojs-hidden-block, .nojs-hidden-table, .nojs-hidden-table-cell {
display: none;
}
.dull {
......
......@@ -22,6 +22,11 @@
</span>
{/foreach}
</div>
<form class="fr nojs-hidden-block" id="bulkactions" action="{$WWWROOT}admin/users/bulk.php" method="post">
{str tag=editselectedusers section=admin}:
<input type="button" class="button" name="go" value="{str tag=go}">
<div id="nousersselected" class="hidden error">{str tag=nousersselected section=admin}</div>
</form>
<form action="{$WWWROOT}admin/users/search.php" method="post">
<div class="searchform">
<label>{str tag='Search' section='admin'}:</label>
......
<img src="{profile_icon_url user=$r maxwidth=40 maxheight=40}" alt="{str tag=profileimage}" />
<input name="selectusers" class="selectusers" type="checkbox" value="{$r.id}">
<a href="{$WWWROOT}admin/users/edit.php?id={$r.id}">{$r.username}</a>
......@@ -18,7 +18,7 @@
{/if}
<tr>
{foreach from=$cols key=f item=c}
<th{if $c.sort} class="search-results-sort-column{if $f == $sortby} {$sortdir}{/if}"{/if}>
<th class="{if $c.sort}search-results-sort-column{if $f == $sortby} {$sortdir}{/if}{/if}{if $c.class} {$c.class}{/if}">
{if $c.sort}
<a href="{$searchurl}&sortby={$f}&sortdir={if $f == $sortby && $sortdir == 'asc'}desc{else}asc{/if}">{$c.name}</a>
{else}
......@@ -37,11 +37,7 @@
{if !$c.template}
{$r[$f]}
{else}
{auto_escape off}
{* auto_escape off seems to be required to eval these templates without errors;
somehow the variables output inside them are getting escaped anyway. *}
{eval var=$c.template}
{/auto_escape}
{include file=$c.template r=$r}
{/if}
</td>{/strip}
{/foreach}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment