MDL-45893 user_menu: based on action_menu, new responsive approach

This commit is contained in:
Jetha Chan 2014-10-03 15:12:37 +08:00
parent d07b0302a9
commit 6da0e4cfff
16 changed files with 637 additions and 12 deletions

View File

@ -94,6 +94,10 @@ class behat_auth extends behat_base {
// If it is needed, it expands the navigation bar with the 'Log out' link.
if ($clicknavbar = $this->get_expand_navbar_step()) {
array_unshift($steps, $clicknavbar);
} else {
// Otherwise we need to expand the the user menu.
$xpath ="//div[@class='usermenu']//a[contains(concat(' ', @class, ' '), ' toggle-display ')]";
array_unshift($steps, new When('I click on "'.$xpath.'" "xpath_element"'));
}
return $steps;

View File

@ -2904,6 +2904,174 @@ EOD;
return html_writer::tag('ul', implode("\n", $lis), $attrs);
}
/**
* Construct a user menu, returning HTML that can be echoed out by a
* layout file.
*
* @param stdClass $user A user object, usually $USER.
* @param bool $withlinks true if a dropdown should be built.
* @return string HTML fragment.
*/
public function user_menu($user = null, $withlinks = false) {
global $USER, $CFG;
if (is_null($user)) {
$user = $USER;
}
// Note: this behaviour is intended to match that of core_renderer::login_info,
// but should not be considered to be good practice; layout options are
// intended to be theme-specific. Please don't copy this snippet anywhere else.
if (is_null($withlinks)) {
$withlinks = empty($this->page->layout_options['nologinlinks']);
}
$returnstr = "";
// If during initial install, return the empty return string.
if (during_initial_install()) {
return $returnstr;
}
$loginpage = ((string)$this->page->url === get_login_url());
$loginurl = get_login_url();
// If not logged in, show the typical not-logged-in string.
if (!isloggedin()) {
$returnstr = get_string('loggedinnot', 'moodle');
if (!$loginpage) {
$returnstr .= " (<a href=\"$loginurl\">" . get_string('login') . '</a>)';
}
return html_writer::tag(
'span',
$returnstr
);
}
// If logged in as a guest user, show a string to that effect.
if (isguestuser()) {
$returnstr = get_string('loggedinasguest');
if (!$loginpage && $withlinks) {
$returnstr .= " (<a href=\"$loginurl\">".get_string('login').'</a>)';
}
return html_writer::tag(
'span',
$returnstr
);
}
// Get some navigation opts.
require_once($CFG->dirroot . '/user/lib.php');
$opts = user_get_user_navigation_info($user, $this->page, $this->page->course);
$avatarclasses = "avatars";
$avatarcontents = html_writer::span($opts->metadata['useravatar'], 'avatar current');
$usertextcontents = $opts->metadata['userfullname'];
// Other user.
if (!empty($opts->metadata['asotheruser'])) {
$avatarcontents .= html_writer::span(
$opts->metadata['realuseravatar'],
'avatar realuser'
);
$usertextcontents = $opts->metadata['realuserfullname'];
$usertextcontents .= html_writer::tag(
'span',
get_string(
'loggedinas',
'moodle',
html_writer::span(
$opts->metadata['userfullname'],
'value'
)
),
array('class' => 'meta viewingas')
);
}
// Role.
if (!empty($opts->metadata['asotherrole'])) {
$role = core_text::strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['rolename'])));
$usertextcontents .= html_writer::span(
$opts->metadata['rolename'],
'meta role role-' . $role
);
}
// User login failures.
if (!empty($opts->metadata['userloginfail'])) {
$usertextcontents .= html_writer::span(
$opts->metadata['userloginfail'],
'meta loginfailures'
);
}
// MNet.
if (!empty($opts->metadata['asmnetuser'])) {
$mnet = strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['mnetidprovidername'])));
$usertextcontents .= html_writer::span(
$opts->metadata['mnetidprovidername'],
'meta mnet mnet-' . $mnet
);
}
$returnstr .= html_writer::span(
html_writer::span($avatarcontents, $avatarclasses) . html_writer::span($usertextcontents, 'usertext'),
'userbutton'
);
// Add a class for when $withlinks is false.
$usermenuclasses = 'usermenu';
if (!$withlinks) {
$usermenuclasses .= ' withoutlinks';
}
// Create a divider (well, a filler).
$divider = new action_menu_filler();
$divider->primary = false;
$am = new action_menu();
$am->initialise_js($this->page);
$am->set_menu_trigger(html_writer::span(
"User menu",
"accesshide"
));
$am->set_alignment(action_menu::TR, action_menu::BR);
if ($withlinks) {
$navitemcount = count($opts->navitems);
$idx = 0;
foreach ($opts->navitems as $key => $value) {
$pix = null;
if (isset($value->pix)) {
$pix = new pix_icon($value->pix, $value->title, null);
}
$al = new action_menu_link_secondary(
$value->url,
$pix,
$value->title,
array('class' => 'icon')
);
$am->add($al);
// Add dividers after the first item and before the
// last item.
if ($idx == 0 || $idx == $navitemcount - 2) {
$am->add($divider);
}
$idx++;
}
}
return html_writer::div(
html_writer::div(
$returnstr,
'userinfo'
) .
$this->render($am),
$usermenuclasses
);
}
/**
* Return the navbar content so that it can be echoed out by the layout
*

View File

@ -66,7 +66,7 @@ echo $OUTPUT->doctype() ?>
<div id="page-header" class="clearfix">
<h1 class="headermain"><?php echo $PAGE->heading ?></h1>
<div class="headermenu"><?php
echo $OUTPUT->login_info();
echo $OUTPUT->user_menu();
echo $OUTPUT->lang_menu();
echo $PAGE->headingmenu;
?></div>

View File

@ -80,9 +80,7 @@ echo $OUTPUT->doctype() ?>
<?php if ($hasheading) { ?>
<h1 class="headermain"><?php echo $PAGE->heading ?></h1>
<div class="headermenu"><?php
if ($haslogininfo) {
echo $OUTPUT->login_info();
}
echo $OUTPUT->user_menu();
if (!empty($PAGE->layout_options['langmenu'])) {
echo $OUTPUT->lang_menu();
}

View File

@ -192,6 +192,106 @@ a.skip:active {position: static;display: block;}
.headermenu {float:right;margin:10px;font-size:0.8em;text-align:right;}
#course-header {clear:both;}
/**
* User menu
*/
.usermenu {
border: 1px solid #333;
padding: 4px 6px;
margin: 0.5em 0em;
font-size: 14px;
}
.jsenabled .usermenu.withoutlinks .moodle-actionmenu[data-enhance]
{
display: none;
}
.usermenu .menu .filler {
width: auto;
height: 1px;
margin: 9px 0px;
display: block;
background: #e5e5e5;
}
.usermenu .toggle-display {
outline: none;
}
.usermenu .userbutton {
background: #fff;
color: #000;
display: inline-block;
font-size: 15px;
}
.usermenu .userbutton > * {
display: inline-block;
vertical-align: middle;
}
.usermenu .userbutton .avatars {
display: inline-block;
vertical-align: middle;
}
.usermenu .userbutton .usertext {
display: inline-block;
text-align: left;
}
.usermenu .userbutton .usertext .meta{
display: block;
font-size: 12px;
}
.usermenu .userbutton .usertext .meta .value {
font-weight: bold;
}
.usermenu .moodle-actionmenu .toggle-display.textmenu .caret {
display: none;
}
.jsenabled .usermenu .moodle-actionmenu[data-enhanced] .toggle-display.textmenu {
margin-left: 0;
padding-left: 0;
}
.jsenabled.dir-rtl .usermenu .moodle-actionmenu[data-enhanced] .toggle-display.textmenu {
margin-right: 0;
margin-left: 4px;
}
.jsenabled .usermenu .moodle-actionmenu[data-enhanced] .toggle-display.textmenu .caret {
display: inline-block;
margin-top: 0;
vertical-align: middle;
}
.userloggedinas .usermenu .userbutton .avatars .avatar {
display: inline-block;
vertical-align:middle;
overflow: hidden;
}
.userloggedinas .usermenu .userbutton .avatars .avatar img {
width: inherit;
height: inherit;
}
.userloggedinas .usermenu .userbutton .avatars .avatar.current {
position: relative;
top: 4px;
left: 4px;
width: 20px;
height: 20px;
margin-top: 11px;
border: 1px solid #ddd;
border-radius: 10px;
box-shadow: -2px -2px 16px rgba(0,0,0,0.25);
}
.dir-ltr .usermenu .userbutton .avatars {
margin-right: 6px;
}
.dir-rtl .usermenu .userbutton {
margin-right: -4px;
}
.dir-rtl .usermenu .userbutton .avatars {
margin-left: 6px;
}
.dir-ltr.userloggedinas .usermenu .userbutton .avatars .avatar.current {
margin-right: -34px;
}
.dir-rtl.userloggedinas .usermenu .userbutton .avatars .avatar.current {
margin-left: -42px;
}
/**
* Navbar
*/

View File

@ -50,7 +50,7 @@ echo $OUTPUT->doctype() ?>
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
<li class="navbar-text"><?php echo $OUTPUT->user_menu() ?></li>
</ul>
</div>
</div>

View File

@ -51,7 +51,7 @@ echo $OUTPUT->doctype() ?>
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
<li class="navbar-text"><?php echo $OUTPUT->user_menu() ?></li>
</ul>
</div>
</div>

View File

@ -56,7 +56,7 @@ echo $OUTPUT->doctype() ?>
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
<li class="navbar-text"><?php echo $OUTPUT->user_menu(); ?></li>
</ul>
</div>
</div>

View File

@ -60,7 +60,7 @@ echo $OUTPUT->doctype() ?>
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
<li class="navbar-text"><?php echo $OUTPUT->user_menu(); ?></li>
</ul>
</div>
</div>
@ -75,6 +75,7 @@ echo $OUTPUT->doctype() ?>
<div class="breadcrumb-button"><?php echo $OUTPUT->page_heading_button(); ?></div>
</div>
<?php echo $OUTPUT->page_heading(); ?>
<?php echo $OUTPUT->user_menu(); ?>
<div id="course-header">
<?php echo $OUTPUT->course_header(); ?>
</div>

View File

@ -340,3 +340,161 @@ div#dock {
border-right: 0px none;
}
}
// Usermenu
.usermenu {
&.withoutlinks {
.withoutlinks {
display: none;
}
}
font-size: 14px;
> .moodle-actionmenu > .menubar {
display: block;
margin: -40px 0px 2px 0px;
li {
display: block;
a {
line-height: 40px;
}
}
}
> div {
height: 40px;
}
.toggle-display {
color: #777;
outline: none;
}
.userbutton {
.avatars{
display: inline-block;
height: 37px;
vertical-align: middle;
margin-right: 6px;
.avatar,
img {
display: block;
}
}
.usertext {
display: inline-block;
vertical-align: middle;
line-height: 1em;
.meta,
.role {
display: block;
font-size: 12px;
.value {
font-weight: bold;
}
}
.role {
font-weight: bold;
}
}
}
.moodle-actionmenu[data-enhanced].show .menu a {
white-space: nowrap;
}
.menu .filler {
width: auto;
height: 1px;
margin: 4px 0px;
display: block;
background: #e5e5e5;
}
}
.userloggedinas .usermenu .userbutton .avatars {
.avatar {
&.current {
position: relative;
top: 4px;
left: 4px;
width: 20px;
height: 20px;
margin-top: 11px;
border: 1px solid #fff;
border-radius: 50%;
box-shadow: -2px -2px 16px rgba(0,0,0,0.25);
}
img {
width: inherit;
height: inherit;
}
display: inline-block;
overflow: hidden;
}
}
.jsenabled .usermenu .moodle-actionmenu[data-enhanced] .toggle-display.textmenu {
position: relative;
.caret {
margin-top: 0;
vertical-align: middle;
}
}
.jsenabled .navbar-inverse {
.usermenu:hover {
.userinfo .usertext {
color: @navbarInverseLinkColorHover;
.meta {
color: @navbarInverseText;
.value {
color: @navbarInverseLinkColorHover;
}
}
}
.moodle-actionmenu[data-enhanced] .toggle-display.textmenu {
.caret {
border-top-color: @navbarInverseLinkColorHover;
}
}
}
}
.dir-ltr {
.usermenu {
.userinfo {
padding-left: 20px;
}
.userbutton {
margin-right: 4px;
padding-right: 16px;
.avatars{
margin-right: 6px;
}
}
> .moodle-actionmenu > .menubar li a {
text-align: right;
}
}
&.userloggedinas .usermenu .userbutton .avatars {
.avatar {
&.current {
margin-right: -34px;
}
}
}
}
.dir-rtl {
.usermenu {
.userbutton {
margin-left: 4px;
padding-left: 16px;
.avatars{
margin-left: 6px;
}
}
> .moodle-actionmenu > .menubar li a {
text-align: left;
}
}
&.userloggedinas .usermenu .userbutton .avatars {
.avatar {
&.current {
margin-left: -42px;
}
}
}
}

View File

@ -440,6 +440,18 @@
}
.nav-collapse.active {
height: auto;
.usermenu .moodle-actionmenu[data-enhanced] {
.toggle-display {
display: none;
}
.menu {
display: block;
li {
margin: 0 0.5em;
}
}
}
}
.path-mod-data .box > table > tbody > tr > td {
display: block;

File diff suppressed because one or more lines are too long

View File

@ -53,7 +53,7 @@ echo $OUTPUT->doctype() ?>
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
<li class="navbar-text"><?php echo $OUTPUT->user_menu() ?></li>
</ul>
</div>
</div>

View File

@ -54,7 +54,7 @@ echo $OUTPUT->doctype() ?>
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
<li class="navbar-text"><?php echo $OUTPUT->user_menu() ?></li>
</ul>
</div>
</div>

View File

@ -65,7 +65,7 @@ echo $OUTPUT->doctype() ?>
<?php echo $OUTPUT->custom_menu(); ?>
<ul class="nav pull-right">
<li><?php echo $OUTPUT->page_heading_menu(); ?></li>
<li class="navbar-text"><?php echo $OUTPUT->login_info() ?></li>
<li class="navbar-text"><?php echo $OUTPUT->user_menu() ?></li>
</ul>
</div>
</div>

View File

@ -614,3 +614,187 @@ function user_count_login_failures($user, $reset = true) {
return $count;
}
/**
* Get a list of essential user navigation items.
*
* @param stdclass $user user object.
* @param moodle_page $page page object.
* @return stdClass $returnobj navigation information object, where:
*
* $returnobj->navitems array array of links where each link is a
* stdClass with fields url, title, and
* pix
* $returnobj->metadata array array of useful user metadata to be
* used when constructing navigation;
* fields include:
*
* ROLE FIELDS
* asotherrole bool whether viewing as another role
* rolename string name of the role
*
* USER FIELDS
* These fields are for the currently-logged in user, or for
* the user that the real user is currently logged in as.
*
* userid int the id of the user in question
* userfullname string the user's full name
* userprofileurl moodle_url the url of the user's profile
* useravatar string a HTML fragment - the rendered
* user_picture for this user
* userloginfail string an error string denoting the number
* of login failures since last login
*
* "REAL USER" FIELDS
* These fields are for when asotheruser is true, and
* correspond to the underlying "real user".
*
* asotheruser bool whether viewing as another user
* realuserid int the id of the user in question
* realuserfullname string the user's full name
* realuserprofileurl moodle_url the url of the user's profile
* realuseravatar string a HTML fragment - the rendered
* user_picture for this user
*
* MNET PROVIDER FIELDS
* asmnetuser bool whether viewing as a user from an
* MNet provider
* mnetidprovidername string name of the MNet provider
* mnetidproviderwwwroot string URL of the MNet provider
*/
function user_get_user_navigation_info($user, $page) {
global $OUTPUT, $DB, $SESSION, $CFG;
$returnobject = new stdClass();
$returnobject->navitems = array();
$returnobject->metadata = array();
$course = $page->course;
// Query the environment.
$context = context_course::instance($course->id);
// Get basic user metadata.
$returnobject->metadata['userid'] = $user->id;
$returnobject->metadata['userfullname'] = fullname($user, true);
$returnobject->metadata['userprofileurl'] = new moodle_url('/user/profile.php', array(
'id' => $user->id
));
$returnobject->metadata['useravatar'] = $OUTPUT->user_picture (
$user,
array(
'link' => false,
'visibletoscreenreaders' => false
)
);
// Build a list of items for a regular user.
// Query MNet status.
if ($returnobject->metadata['asmnetuser'] = is_mnet_remote_user($user)) {
$mnetidprovider = $DB->get_record('mnet_host', array('id' => $user->mnethostid));
$returnobject->metadata['mnetidprovidername'] = $mnetidprovider->name;
$returnobject->metadata['mnetidproviderwwwroot'] = $mnetidprovider->wwwroot;
}
// Did the user just log in?
if (isset($SESSION->justloggedin)) {
// Don't unset this flag as login_info still needs it.
if (!empty($CFG->displayloginfailures)) {
// We're already in /user/lib.php, so we don't need to include.
if ($count = user_count_login_failures($user)) {
// Get login failures string.
$a = new stdClass();
$a->attempts = html_writer::tag('span', $count, array('class' => 'value'));
$returnobject->metadata['userloginfail'] =
get_string('failedloginattempts', '', $a);
}
}
}
// Links: My Home.
$myhome = new stdClass();
$myhome->url = new moodle_url('/my/');
$myhome->title = get_string('mymoodle', 'admin');
$myhome->pix = "i/course";
$returnobject->navitems[] = $myhome;
// Links: My Profile.
$myprofile = new stdClass();
$myprofile->url = new moodle_url('/user/profile.php', array('id' => $user->id));
$myprofile->title = get_string('myprofile');
$myprofile->pix = "i/user";
$returnobject->navitems[] = $myprofile;
// Links: Role-return or logout link.
$lastobj = null;
$buildlogout = true;
$returnobject->metadata['asotherrole'] = false;
if (is_role_switched($course->id)) {
if ($role = $DB->get_record('role', array('id' => $user->access['rsw'][$context->path]))) {
// Build role-return link instead of logout link.
$rolereturn = new stdClass();
$rolereturn->url = new moodle_url('/course/switchrole.php', array(
'id' => $course->id,
'sesskey' => sesskey(),
'switchrole' => 0,
'returnurl' => $page->url->out_as_local_url(false)
));
$rolereturn->pix = "a/logout";
$rolereturn->title = get_string('switchrolereturn');
$lastobj = $rolereturn;
$returnobject->metadata['asotherrole'] = true;
$returnobject->metadata['rolename'] = role_get_name($role, $context);
$buildlogout = false;
}
}
if ($returnobject->metadata['asotheruser'] = \core\session\manager::is_loggedinas()) {
$realuser = \core\session\manager::get_realuser();
// Save values for the real user, as $user will be full of data for the
// user the user is disguised as.
$returnobject->metadata['realuserid'] = $realuser->id;
$returnobject->metadata['realuserfullname'] = fullname($realuser, true);
$returnobject->metadata['realuserprofileurl'] = new moodle_url('/user/profile.php', array(
'id' => $realuser->id
));
$returnobject->metadata['realuseravatar'] = $OUTPUT->user_picture (
$realuser,
array(
'link' => false,
'visibletoscreenreaders' => false
)
);
// Build a user-revert link.
$userrevert = new stdClass();
$userrevert->url = new moodle_url('/course/loginas.php', array(
'id' => $course->id,
'sesskey' => sesskey()
));
$userrevert->pix = "a/logout";
$userrevert->title = get_string('logout');
$lastobj = $userrevert;
$buildlogout = false;
}
if ($buildlogout) {
// Build a logout link.
$logout = new stdClass();
$logout->url = new moodle_url('/login/logout.php', array('sesskey' => sesskey()));
$logout->pix = "a/logout";
$logout->title = get_string('logout');
$lastobj = $logout;
}
// Add the last item to the list.
if (!is_null($lastobj)) {
$returnobject->navitems[] = $lastobj;
}
return $returnobject;
}