Commit 6cd4de6a authored by Naomi Guyer's avatar Naomi Guyer Committed by Aaron Wells

User search (bootstrap)

Bug 1465107: Use Bootstrap CSS Framework

Change-Id: I4703db38c49d2fe9c60fbecce49be91b2d92ea27
parent a17bbc39
......@@ -73,10 +73,14 @@ $calendarform = new Pieform(array(
'loggedindate' => $calendar,
),
));
$calendarform->include_plugin('element', 'calendar');
$loggedindate = pieform_element_calendar($calendarform, $calendar);
list($html, $columns, $pagination, $search) = build_admin_user_search_results($search, $offset, $limit);
$searchParams = $search; //store search as it's about to change
list($html, $columns, $pagination, $search) = build_admin_user_search_results($search, $offset, $limit, $search);
$js = <<<EOF
addLoadEvent(function() {
......@@ -87,7 +91,7 @@ addLoadEvent(function() {
EOF;
$smarty = smarty(array('adminusersearch', 'paginator'), array(), array('ascending' => 'mahara', 'descending' => 'mahara'));
$smarty->assign('search', $search);
$smarty->assign('search', $searchParams);
$smarty->assign('limit', $limit);
$smarty->assign('loggedintypes', $loggedintypes);
$smarty->assign('loggedindate', $loggedindate);
......@@ -101,4 +105,5 @@ $smarty->assign('sortby', $search['sortby']);
$smarty->assign('sortdir', $search['sortdir']);
$smarty->assign('INLINEJAVASCRIPT', $js);
$smarty->assign('PAGEHEADING', TITLE);
$smarty->assign('PAGEICON', 'fa fa-search');
$smarty->display('admin/users/search.tpl');
......@@ -125,11 +125,20 @@ function UserSearch(pager) {
var value = $j(this).val();
$j(this).change(function() {
if ($j(this).prop('checked')) {
$j(this).closest('tr').addClass('warning'); // visual selected indicator
self.selectusers[value] = 1;
}
else {
$j(this).closest('tr').removeClass('warning'); // visual selected indicator
delete self.selectusers[value];
}
//update button state
if($j('#searchresults input.selectusers:checked').length > 0){
$j('.withselectedusers button').removeClass('disabled');
}
else {
$j('.withselectedusers button').addClass('disabled');
}
});
if (self.selectusers[value]) {
$j(this).prop('checked', true);
......@@ -137,16 +146,24 @@ function UserSearch(pager) {
});
if ($j('#selectall')) {
$j('#selectall').click(function() {
$j(this).addClass('active');
$j(this).siblings().removeClass('active');
$j('.withselectedusers button').removeClass('disabled');
$j('#searchresults input.selectusers').each(function() {
self.selectusers[$j(this).val()] = 1;
$j(this).prop('checked', true);
$j(this).closest('tr').addClass('warning'); // visual selected indicator
});
return false;
});
$j('#selectnone').click(function() {
$j(this).addClass('active');
$j(this).siblings().removeClass('active');
$j('.withselectedusers button').addClass('disabled');
$j('#searchresults input.selectusers').each(function() {
delete self.selectusers[$j(this).val()];
$j(this).prop('checked', false);
$j(this).closest('tr').removeClass('warning'); // visual selected indicator
});
return false;
});
......@@ -184,7 +201,7 @@ function UserSearch(pager) {
};
this.connectSelectedUsersForm = function(i, formid) {
$j('#' + formid + ' input.button').click(function() {
$j('#' + formid + ' button').click(function() {
// Some of the selected users aren't on the page, so just add them all to the
// form now.
var count = 0;
......
......@@ -1140,7 +1140,7 @@ $string['usershaveloggedinsince'] = 'Users have logged in since';
$string['usershavenotloggedinsince'] = 'Users have not logged in since';
// Admin user search duplicate email filter
$string['duplicateemailfilter'] = 'Filter by duplicate email addresses:';
$string['duplicateemailfilter'] = 'Duplicate email addresses';
$string['lastlogin'] = 'Last login';
......
......@@ -414,10 +414,19 @@ function build_admin_user_search_results($search, $offset, $limit) {
'jsonscript' => 'admin/users/search.json.php',
));
$cols = array(
'select' => array(
'mergefirst' => true,
'headhtml' => '<div class="btn-group" role="group"><a class="btn btn-xs btn-default" href="" id="selectall">' . get_string('All') . '</a>&nbsp;<a class="btn active btn-xs btn-default" href="" id="selectnone">' . get_string('none') . '</a></div>',
'template' => 'admin/users/searchselectcolumn.tpl',
'class' => 'nojs-hidden with-checkbox',
'accessible' => get_string('bulkselect'),
),
'icon' => array(
'mergelast' => true,
'template' => 'admin/users/searchiconcolumn.tpl',
'class' => 'center',
'accessible' => get_string('profileicon'),
),
'firstname' => array(
......@@ -475,12 +484,7 @@ function build_admin_user_search_results($search, $offset, $limit) {
'template' => 'strftimedatetime.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',
'accessible' => get_string('bulkselect'),
);
if (!$USER->get('admin') && !$USER->is_institutional_admin()) {
unset($cols['email']);
......
......@@ -16,4 +16,8 @@
background-color: rgba(#fff, 0.4);
border: 1px solid darken($brand-default, 5%);
color: #555;
}
.fullwidth {
width: 100%;
}
\ No newline at end of file
.pseudolabel {
font-weight: bold;
vertical-align: top;
width: 200px;
margin: 10px 0;
padding-right: 10px;
display: inline-block;
}
.message {
font-size: 0.9em;
......@@ -24,24 +17,34 @@ label.sr-only + div.mce-tinymce {
width: 100%;
}
.main form .form-group {
label,
.pseudolabel {
@extend .control-label;
min-width: 200px;
padding-right: 10px;
font-weight:normal;
font-size: 1.1em;
.pseudolabel {
vertical-align: top;
padding-right: 10px;
display: inline-block;
}
label,
.pseudolabel {
@extend .control-label;
min-width: 200px;
max-width: 100%;
padding-right: 10px;
font-weight:normal;
font-size: 1.1em;
.col-md-2 & {
min-width:0;
}
}
.stacked-label {
display: inline-block;
@media (min-width: $screen-sm-min) {
width:200px;
}
.stacked-label {
display: inline-block;
@media (min-width: $screen-sm-min) {
width:200px;
}
}
.as-panel form {
margin-top:0;
}
......@@ -362,3 +365,14 @@ select {
}
}
.inline {
label {
line-height: 33px;
max-width: 30%;
}
label, input, select {
display:inline-block;
max-width: 200px;
min-width:0;
}
}
\ No newline at end of file
.label {
&.label-default {
color: #333;
&:hover,
&:focus {
background-color:$mahara-green-bright;
}
}
}
\ No newline at end of file
......@@ -106,4 +106,45 @@ blockquote {
&.small {
font-size: $font-size-base;
}
}
.table-small{
font-size: 0.8em;
th {
font-size: 0.8em;
}
>thead>tr>th,
>thead>tr>td,
>tbody>tr>th,
>tbody>tr>td,
>tfoot>tr>th,
>tfoot>tr>td {
padding: 5px 3px;
&:first-child {
padding-left:8px;
}
&:last-child {
padding-right: 8px;
}
}
> thead>tr> th {
padding: 10px 3px;
}
.btn-xs {
font-size: 10px;
}
}
table.table tr {
.with-checkbox {
min-width: 74px;
input {
margin-top:12px;
margin-right:3px;
float:left;
}
}
}
\ No newline at end of file
......@@ -82,6 +82,7 @@
// General customisation and component files go here...
@import "utilities/classes"; // Custom utility classes
@import "utilities/whitespace"; // Custom utility classes
@import "components/label";
@import "components/typography";
@import "components/forms";
@import "components/collapse";
......
......@@ -60,6 +60,7 @@
padding-right: 30px;
}
//
// Margin
//
......@@ -117,3 +118,128 @@
.mrxl {
margin-right: 30px;
}
// Desktop only whitespace
@media (min-width: $screen-md-min) {
//
// Padding
//
// Padding Top
.pts-md {
padding-top: 5px;
}
.ptm-md {
padding-top: 10px;
}
.ptl-md {
padding-top: 20px;
}
.ptxl-md {
padding-top: 30px;
}
// Padding bottom
.pbs-md {
padding-bottom: 5px;
}
.pbm-md {
padding-bottom: 10px;
}
.pbl-md {
padding-bottom: 20px;
}
.pbxl-md {
padding-bottom: 30px;
}
// Padding left
.pls-md {
padding-left: 5px;
}
.plm-md {
padding-left: 10px;
}
.pll-md {
padding-left: 20px;
}
.plxl-md {
padding-left: 30px;
}
// Padding right
.prs-md {
padding-right: 5px;
}
.prm-md {
padding-right: 10px;
}
.prl-md {
padding-right: 20px;
}
.prxl-md {
padding-right: 30px;
}
//
// Margin
//
//margin top
.mts-md {
margin-top: 5px;
}
.mtm-md {
margin-top: 10px;
}
.mtl-md {
margin-top: 20px;
}
.mtxl-md {
margin-top: 30px;
}
//margin bottom
.mbs-md {
margin-bottom: 5px;
}
.mbm-md {
margin-bottom: 10px;
}
.mbl-md {
margin-bottom: 20px;
}
.mbxl-md {
margin-bottom: 30px;
}
//margin left
.mls-md {
margin-left: 5px;
}
.mlm-md {
margin-left: 10px;
}
.mll-md {
margin-left: 20px;
}
.mlxl-md {
margin-left: 30px;
}
//margin right
.mrs-md {
margin-right: 5px;
}
.mrm-md {
margin-right: 10px;
}
.mrl-md {
margin-right: 20px;
}
.mrxl-md {
margin-right: 30px;
}
}
......@@ -178,8 +178,8 @@ $table-border-color: #ddd !default;
$btn-font-weight: normal !default;
$btn-default-color: #333 !default;
$btn-default-bg: #ccc !default;
$btn-default-border: #555 !default;
$btn-default-bg: #ddd !default;
$btn-default-border: #ccc !default;
$btn-primary-color: #fff !default;
$btn-primary-bg: $brand-primary !default;
......@@ -568,7 +568,7 @@ $popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%
//##
//** Default label background color
$label-default-bg: $gray-light !default;
$label-default-bg: $brand-default !default;
//** Primary label background color
$label-primary-bg: $brand-primary !default;
//** Success label background color
......
This source diff could not be displayed because it is too large. You can view the blob instead.
{include file="header.tpl"}
<div class="row">
<div class="col-md-12">
<p class="lead">{str tag="usersearchinstructions" section="admin"}</p>
</div>
</div>
<div class="row">
<div class="col-md-3 prs-md">
<p>{str tag="usersearchinstructions" section="admin"}</p>
<span class="accessible-hidden sr-only" tabindex="0">{str tag="filterresultsby"}</span>
<div id="initials">
<div id="firstnamelist">
<strong id="firstname">{str tag="firstname"}:</strong>
<span class="first-initial{if !$search->f} selected{/if} all">
<a aria-labelledby="firstname" aria-label="{str tag="firstnameall"}" href="{$WWWROOT}admin/users/search.php?query={$search->query}{if $search->l}&amp;l={$search->l}{/if}{if $search->sortby}&amp;sortby={$search->sortby}{/if}{if $search->sortdir}&amp;sortdir={$search->sortdir}{/if}{if $limit}&amp;limit={$limit}{/if}">{str tag="All"}</a>
</span>
{foreach from=$alphabet item=a}
<span class="first-initial{if $a == $search->f} selected{/if}">
<a aria-labelledby="firstname" aria-label="{str tag="firstname"}" href="{$WWWROOT}admin/users/search.php?query={$search->query}&amp;f={$a}{if $search->l}&amp;l={$search->l}{/if}{if $search->sortby}&amp;sortby={$search->sortby}{/if}{if $search->sortdir}&amp;sortdir={$search->sortdir}{/if}{if $limit}&amp;limit={$limit}{/if}">{$a}</a>
</span>
{/foreach}
</div>
<div id="lastnamelist">
<strong id="lastname">{str tag="lastname"}:</strong>
<span class="last-initial{if !$search->l} selected{/if} all">
<a aria-labelledby="lastname" aria-label="{str tag="lastnameall"}" href="{$WWWROOT}admin/users/search.php?query={$search->query}{if $search->f}&amp;f={$search->f}{/if}{if $search->sortby}&amp;sortby={$search->sortby}{/if}{if $search->sortdir}&amp;sortdir={$search->sortdir}{/if}{if $limit}&amp;limit={$limit}{/if}">{str tag="All"}</a>
</span>
{foreach from=$alphabet item=a}
<span class="last-initial{if $a == $search->l} selected{/if}">
<a aria-labelledby="lastname" aria-label="{str tag="lastname"}" href="{$WWWROOT}admin/users/search.php?query={$search->query}&amp;l={$a}{if $search->f}&amp;f={$search->f}{/if}{if $search->sortby}&amp;sortby={$search->sortby}{/if}{if $search->sortdir}&amp;sortdir={$search->sortdir}{/if}{if $limit}&amp;limit={$limit}{/if}">{$a}</a>
</span>
{/foreach}
</div>
<div class="panel panel-default">
<h3 class="panel-heading" tabindex="0">{str tag="filterresultsby"}</h3>
<div class="panel-body">
<div id="initials" class="initials">
<div id="firstnamelist">
<p class="pseudolabel" id="firstname">{str tag="firstname"}:</p>
<br/>
<a class="label first-initial{if !$search->f} label-primary active{else} label-default{/if} all" aria-labelledby="firstname" aria-label="{str tag="firstnameall"}" href="{$WWWROOT}admin/users/search.php?query={$search->query}{if $search->l}&amp;l={$search->l}{/if}{if $search->sortby}&amp;sortby={$search->sortby}{/if}{if $search->sortdir}&amp;sortdir={$search->sortdir}{/if}{if $limit}&amp;limit={$limit}{/if}">{str tag="All"}</a>
{foreach from=$alphabet item=a}
<a class="label first-initial{if $a == $search->f} label-primary active{else} label-default{/if}" aria-labelledby="firstname" aria-label="{str tag="firstname"}" href="{$WWWROOT}admin/users/search.php?query={$search->query}&amp;f={$a}{if $search->l}&amp;l={$search->l}{/if}{if $search->sortby}&amp;sortby={$search->sortby}{/if}{if $search->sortdir}&amp;sortdir={$search->sortdir}{/if}{if $limit}&amp;limit={$limit}{/if}">{$a}</a>
{/foreach}
</div>
<div class="mtl" id="lastnamelist">
<p class="pseudolabel" id="lastname">{str tag="lastname"}:</p>
<br/>
<a class="label last-initial{if !$search->l} label-primary active{else} label-default{/if} all" aria-labelledby="lastname" aria-label="{str tag="lastnameall"}" href="{$WWWROOT}admin/users/search.php?query={$search->query}{if $search->f}&amp;f={$search->f}{/if}{if $search->sortby}&amp;sortby={$search->sortby}{/if}{if $search->sortdir}&amp;sortdir={$search->sortdir}{/if}{if $limit}&amp;limit={$limit}{/if}">{str tag="All"}</a>
{foreach from=$alphabet item=a}
<a class="label last-initial{if $a == $search->l} label-primary active{else} label-default{/if}" aria-labelledby="lastname" aria-label="{str tag="lastname"}" href="{$WWWROOT}admin/users/search.php?query={$search->query}&amp;l={$a}{if $search->f}&amp;f={$search->f}{/if}{if $search->sortby}&amp;sortby={$search->sortby}{/if}{if $search->sortdir}&amp;sortdir={$search->sortdir}{/if}{if $limit}&amp;limit={$limit}{/if}">{$a}</a>
{/foreach}
</div>
</div>
<form class="mtm" action="{$WWWROOT}admin/users/search.php" method="post">
{if $search->f}
<input type="hidden" name="f" id="f" value="{$search->f}">
{/if}
{if $search->l}
<input type="hidden" name="l" id="l" value="{$search->l}">
{/if}
{if $search->sortby}
<input type="hidden" name="sortby" id="sortby" value="{$search->sortby}">
{/if}
{if $search->sortdir}
<input type="hidden" name="sortdir" id="sortdir" value="{$search->sortdir}">
{/if}
{if $limit}
<input type="hidden" name="limit" id="limit" value="{$limit}">
{/if}
<hr />
<div class="loggedin-filter mtl">
<label for="loggedin">{str tag="lastlogin" section="admin"}</label>
<select name="loggedin" id="loggedin">
{foreach from=$loggedintypes item=t}
<option value="{$t['name']}"{if $search->loggedin === $t['name']} selected="selected"{/if}>{$t['string']}</option>
{/foreach}
</select>
<span id="loggedindate_container"{if !($search->loggedin == 'since' || $search->loggedin == 'notsince')} class="js-hidden"{/if}>
{$loggedindate|safe}
</span>
</div>
<div class="duplicateemail-filter mtm">
<label for="duplicateemail">
<input type="checkbox" name="duplicateemail" id="duplicateemail" value="1"{if $search->duplicateemail} checked{/if}>
{str tag="duplicateemailfilter" section="admin"}
</label>
</div>
</div>
</div>
</form>
</div>
<form action="{$WWWROOT}admin/users/search.php" method="post">
{if $search->f}
<input type="hidden" name="f" id="f" value="{$search->f}">
{/if}
{if $search->l}
<input type="hidden" name="l" id="l" value="{$search->l}">
{/if}
{if $search->sortby}
<input type="hidden" name="sortby" id="sortby" value="{$search->sortby}">
{/if}
{if $search->sortdir}
<input type="hidden" name="sortdir" id="sortdir" value="{$search->sortdir}">
{/if}
{if $limit}
<input type="hidden" name="limit" id="limit" value="{$limit}">
{/if}
<div class="loggedin-filter">
<label for="loggedin">{str tag="loggedinfilter" section="admin"}</label>
<select name="loggedin" id="loggedin">
{foreach from=$loggedintypes item=t}
<option value="{$t['name']}"{if $search->loggedin === $t['name']} selected="selected"{/if}>{$t['string']}</option>
{/foreach}
</select>
<span id="loggedindate_container"{if !($search->loggedin == 'since' || $search->loggedin == 'notsince')} class="js-hidden"{/if}>
{$loggedindate|safe}
</span>
</div>
<div class="duplicateemail-filter">
<label for="duplicateemail">{str tag="duplicateemailfilter" section="admin"}</label>
<input type="checkbox" name="duplicateemail" id="duplicateemail" value="1"{if $search->duplicateemail} checked{/if}>
</div>
<div class="usersearchform">
<label for="query">{str tag='Search' section='admin'}:</label>
<input type="text" name="query" id="query"{if $search->query} value="{$search->query}"{/if}>
{if count($institutions) > 1}
<span class="institutions">
<label for="institution">{str tag='Institution' section='admin'}:</label>
<select name="institution" id="institution">
<option value="all"{if !$.request.institution} selected="selected"{/if}>{str tag=All}</option>
{foreach from=$institutions item=i}
<option value="{$i->name}"{if $i->name == $.request.institution}" selected="selected"{/if}>{$i->displayname}</option>
{/foreach}
</select>
</span>
<div class="col-md-9 pls-md">
<div class="panel panel-default mbm">
<h3 class="sr-only panel-heading">{str tag='Search' section='admin'}</h3>
<div class="panel-body">
<div class="usersearchform inline">
<label class="pull-left" for="query">{str tag='Search' section='admin'}:</label>
<input class="pull-left" type="text" name="query" id="query"{if $search->query} value="{$search->query}"{/if}>
</div>
{if count($institutions) > 1}
<div class="institutions inline">
<label class="pull-left mlm" for="institution">{str tag='Institution' section='admin'}:</label>
<select class="pull-left" name="institution" id="institution">
<option value="all"{if !$.request.institution} selected="selected"{/if}>{str tag=All}</option>
{foreach from=$institutions item=i}
<option value="{$i->name}"{if $i->name == $.request.institution}" selected="selected"{/if}>{$i->displayname}</option>
{/foreach}
</select>
</div>