--- loncom/interface/lonmenu.pm 2012/12/27 00:24:45 1.401
+++ loncom/interface/lonmenu.pm 2022/05/28 16:25:45 1.520
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Routines to control the menu
#
-# $Id: lonmenu.pm,v 1.401 2012/12/27 00:24:45 raeburn Exp $
+# $Id: lonmenu.pm,v 1.520 2022/05/28 16:25:45 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -99,17 +99,18 @@ It gets filled in the BEGIN block of thi
=over
-=item prep_menuitems(\@menuitem)
+=item prep_menuitems(\@menuitem,$ltitarget,$deeplinktarget,$listclass,$linkattr)
This routine wraps a menuitem in proper HTML. It is used by primary_menu() and
secondary_menu().
=item primary_menu()
-This routine evaluates @primary_menu and returns XHTML for the menu
-that contains following links: About, Message, Roles, Help, Logout
+This routine evaluates @primary_menu and returns a two item array,
+with the array elements containing XHTML for the left and right sides of
+the menu that contains the following links: About, Message, Roles, Help, Logout
@primary_menu is filled within the BEGIN block of this module with
-entries from mydesk.tab
+entries from mydesk.tab
=item secondary_menu()
@@ -123,9 +124,40 @@ dropdown list when mouse hovers over top
(no hover psuedo class) via LC_hoverable class for
tag for top-
level item, which employs jQuery to handle behavior on mouseover.
-Inputs: 4 - (a) link and (b) target for anchor href in top level item,
- (c) title for text wrapped by anchor tag in top level item.
- (d) reference to array of arrays of sub-menu items.
+Inputs: 6 - (a) link and (b) target for anchor href in top level item,
+ (c) title for text wrapped by anchor tag in top level item,
+ (d) reference to array of arrays of sub-menu items,
+ (e) boolean to indicate whether to call &mt() to translate
+ name of menu item,
+ (f) optional class for
element in primary menu, for which
+ sub menu is being generated.
+
+ The underlying datastructure used in (d) contains data from mydesk.tab.
+ It consists of an array which has an array for each item appearing in
+ the menu (e.g. [["link", "title", "condition"]] for a single-item menu).
+ create_submenu() supports also the creation of XHTML for nested dropdown
+ menus represented by unordered lists. This is done by replacing the
+ scalar used for the link with an arrayreference containing the menuitems
+ for the nested menu. This can be done recursively so that the next menu
+ may also contain nested submenus.
+
+ Example:
+ [ # begin of datastructure
+ ["/home/", "Home", "condition1"], # 1st item of the 1st layer menu
+ [ # 2nd item of the 1st layer menu
+ [ # anon. array for nested menu
+ ["/path1", "Path1", undef], # 1st item of the 2nd layer menu
+ ["/path2", "Path2", undef], # 2nd item of the 2nd layer menu
+ [ # 3rd item of the 2nd layer menu
+ [[...], [...], ..., [...]], # containing another menu layer
+ "Sub-Sub-Menu", # title for this container
+ undef
+ ]
+ ], # end of array/nested menu
+ "Sub-Menu", # title for the container item
+ undef
+ ] # end of 2nd item of the 1st layer menu
+]
=item innerregister()
@@ -178,16 +210,17 @@ use Apache::lonenc();
use Apache::lonlocal;
use Apache::lonmsg();
use LONCAPA qw(:DEFAULT :match);
+use LONCAPA::ltiutils;
use HTML::Entities();
use Apache::lonwishlist();
use vars qw(@desklines %category_names %category_members %category_positions
- $readdesk @primary_menu %primary_submenu @secondary_menu);
+ $readdesk @primary_menu %primary_submenu @secondary_menu %secondary_submenu);
my @inlineremote;
sub prep_menuitem {
- my ($menuitem) = @_;
+ my ($menuitem,$ltitarget,$deeplinktarget,$listclass,$linkattr) = @_;
return '' unless(ref($menuitem) eq 'ARRAY');
my $link;
if ($$menuitem[1]) { # graphical Link
@@ -197,26 +230,61 @@ sub prep_menuitem {
} else { # textual Link
$link = &mt($$menuitem[3]);
}
- return '
|;
}
-# primary_menu() evaluates @primary_menu and returns XHTML for the menu
-# that contains following links:
-# About, Message, Personal, Roles, Help, Logout
+# primary_menu() evaluates @primary_menu and returns a two item array,
+# with the array elements containing XHTML for the left and right sides of
+# the menu that contains the following links:
+# Personal, About, Message, Roles, Help, Logout
# @primary_menu is filled within the BEGIN block of this module with
# entries from mydesk.tab
sub primary_menu {
- my $menu;
+ my ($crstype,$ltimenu,$menucoll,$menuref,$links_disabled) = @_;
+ my (%menu,%ltiexc,%menuopts);
# each element of @primary contains following array:
- # (link url, icon path, alt text, link text, condition)
+ # (link url, icon path, alt text, link text, condition, position)
my $public;
if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
|| (($env{'user.name'} eq '') && ($env{'user.domain'} eq ''))) {
$public = 1;
}
+ my $rolecount;
+ if (($crstype eq 'Placement') && (!$env{'request.role.adv'})) {
+ my $update=$env{'user.update.time'};
+ if (!$update) {
+ $update = $env{'user.login.time'};
+ }
+ my %roles_in_env;
+ $rolecount = &Apache::lonroles::roles_from_env(\%roles_in_env,$update);
+ }
+ my ($lti,$ltitarget,$deeplinktarget);
+ if ($env{'request.lti.login'}) {
+ $lti = 1;
+ $ltitarget = $env{'request.lti.target'};
+ if (ref($ltimenu) eq 'HASH') {
+ foreach my $item ('fullname','logout') {
+ unless ($ltimenu->{$item}) {
+ $ltiexc{$item} = 1;
+ }
+ }
+ }
+ }
+ if ($env{'request.deeplink.login'}) {
+ $deeplinktarget = $env{'request.deeplink.target'};
+ }
+ if (($menucoll) && (ref($menuref) eq 'HASH')) {
+ %menuopts = %{$menuref};
+ }
foreach my $menuitem (@primary_menu) {
# evaluate conditions
next if ref($menuitem) ne 'ARRAY'; #
@@ -231,37 +299,96 @@ sub primary_menu {
&& !$public; # only visible to public
# users
next if $$menuitem[4] eq 'roles' ##show links depending on
- && &Apache::loncommon::show_course(); ##term 'Courses' or
- next if $$menuitem[4] eq 'courses' ##'Roles' wanted
- && !&Apache::loncommon::show_course(); ##
-
+ && (&Apache::loncommon::show_course() ##term 'Courses' or
+ || $lti); ##'Roles' wanted
+ next if $$menuitem[4] eq 'courses' ##and not LTI access
+ && (!&Apache::loncommon::show_course()
+ || $lti);
+ next if $$menuitem[4] eq 'notlti'
+ && $lti;
+ next if $$menuitem[4] eq 'ltiexc'
+ && exists($ltiexc{lc($menuitem->[3])});
my $title = $menuitem->[3];
+ if (($crstype eq 'Placement') && (!$env{'request.role.adv'})) {
+ if ($menuitem->[4] eq 'courses') {
+ next unless ($rolecount>1);
+ } else {
+ next unless (($title eq 'Personal') || ($title eq 'Logout'));
+ }
+ }
+ my $position = $menuitem->[5];
+ if ($position eq '') {
+ $position = 'right';
+ }
+ if ($env{'request.course.id'} && $menucoll) {
+ if (($menuitem->[6]) && (!$menuopts{$menuitem->[6]})) {
+ if ($menuitem->[6] eq 'pers') {
+ if ($menuopts{'name'} && !$ltiexc{'fullname'} &&
+ $env{'user.name'} && $env{'user.domain'}) {
+ $menu{$position} .= '
';
+
+ # $link and $title are only used in the initial string written in $menu
+ # as seen above, not needed for nested submenus
+ $menu .= &build_submenu($target, $submenu, $translate, '1', $listclass, $linkattr);
+ $menu .= '
';
+
+ return $menu;
+}
+
+# helper routine for create_submenu
+# build the dropdown (and nested submenus) recursively
+# see perldoc create_submenu documentation for further information
+sub build_submenu {
+ my ($target, $submenu, $translate, $first_level, $listclass, $linkattr) = @_;
+ unless (@{$submenu}) {
+ return '';
+ }
+
+ my $menu = '';
my $count = 0;
my $numsub = scalar(@{$submenu});
foreach my $item (@{$submenu}) {
$count ++;
if (ref($item) eq 'ARRAY') {
+ my $href = $item->[0];
+ my $bordertop;
my $borderbot;
+ my $title;
+
+ if ($translate) {
+ $title = &mt($item->[1]);
+ } else {
+ $title = $item->[1];
+ }
+
+ if ($count == 1 && !$first_level) {
+ $bordertop = 'border-top: 1px solid black;';
+ }
if ($count == $numsub) {
- $borderbot = 'border-bottom:1px solid black;';
+ $borderbot = 'border-bottom: 1px solid black;';
+ }
+
+ # href is a reference to another submenu
+ if (ref($href) eq 'ARRAY') {
+ $menu .= '
';
+ if ($type eq 'map') {
+ $lt{'miss'} .= &mt('Submissions are missing for [quant,_1,question part,question parts] in this folder.',$missing);
+ } else {
+ $lt{'miss'} .= &mt('Submissions are missing for [quant,_1,part] in this question.',$missing);
+ }
+ if ($missing > 1) {
+ $lt{'miss'} .= ' '.&mt('If you confirm you are done you will be unable to submit answers for them.').'';
+ } else {
+ $lt{'miss'} .= ' '.&mt('If you confirm you are done you will be unable to submit an answer for it.').'