--- loncom/interface/courseprefs.pm 2021/12/15 00:48:41 1.49.2.27
+++ loncom/interface/courseprefs.pm 2022/01/16 23:34:19 1.49.2.28.2.2
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set configuration settings for a course
#
-# $Id: courseprefs.pm,v 1.49.2.27 2021/12/15 00:48:41 raeburn Exp $
+# $Id: courseprefs.pm,v 1.49.2.28.2.2 2022/01/16 23:34:19 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -365,9 +365,15 @@ sub handler {
}
my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
+ my %courselti=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
+ if ($courselti{'lock'}) {
+ delete($courselti{'lock'});
+ }
+ $values{'linkprotection'} = \%courselti;
my @prefs_order = ('courseinfo','localization','feedback','discussion',
'classlists','appearance','grading','printouts',
- 'spreadsheet','bridgetasks','other');
+ 'menuitems','linkprotection','spreadsheet','bridgetasks',
+ 'other');
my %prefs = (
'courseinfo' =>
@@ -464,7 +470,7 @@ sub handler {
help => 'Course_Prefs_Display',
ordered => ['default_xml_style','pageseparators',
'disable_receipt_display','texengine',
- 'tthoptions','uselcmath','usejsme'],
+ 'tthoptions','uselcmath','usejsme','inline_chem'],
itemtext => {
default_xml_style => 'Default XML style file',
pageseparators => 'Visibly Separate Items on Pages',
@@ -473,6 +479,7 @@ sub handler {
tthoptions => 'Default set of options to pass to tth/m when converting TeX',
uselcmath => 'Student formula entry uses inline preview, not DragMath pop-up',
usejsme => 'Molecule editor uses JSME (HTML5) in place of JME (Java)',
+ inline_chem => 'Chemical reaction response uses inline preview, not pop-up',
},
},
'grading' =>
@@ -527,6 +534,29 @@ sub handler {
suppress_embed_prompt => 'Hide upload references prompt if uploading file to portfolio',
},
},
+ 'menuitems' =>
+ {
+ text => 'Menu display',
+ help => 'Course_Prefs_Menus',
+ header => [{col1 => 'Default Menu',
+ col2 => 'Value',},
+ {col1 => 'Menu collections',
+ col2 => 'Settings',
+ }],
+ ordered => ['menudefault','menucollections'],
+ itemtext => {
+ menudefault => 'Choose default collection of menu items for course',
+ menucollections => 'Menu collections',
+ },
+ },
+ 'linkprotection' =>
+ {
+ text => 'Link protection',
+ help => 'Course_Prefs_Linkprotection',
+ header => [{col1 => 'Item',
+ col2 => 'Settings',
+ }],
+ },
'other' =>
{ text => 'Other settings',
help => 'Course_Prefs_Other',
@@ -542,7 +572,13 @@ sub handler {
$cnum,undef,\@allitems,
'coursepref',$parm_permission);
} elsif (($phase eq 'display') && ($parm_permission->{'display'})) {
- my $jscript = &get_jscript($cid,$cdom,$phase,$crstype,\%values);
+ my $noedit;
+ if (ref($parm_permission) eq 'HASH') {
+ unless ($parm_permission->{'process'}) {
+ $noedit = 1;
+ }
+ }
+ my $jscript = &get_jscript($cid,$cdom,$phase,$crstype,\%values,$noedit);
my @allitems = &get_allitems(%prefs);
&Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context,
\@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype,
@@ -619,7 +655,7 @@ sub print_config_box {
}
$output .= ''."\n".
'';
- if (($action eq 'feedback') || ($action eq 'classlists')) {
+ if (($action eq 'feedback') || ($action eq 'classlists') || ($action eq 'menuitems')) {
$output .= '
@@ -644,6 +680,8 @@ sub print_config_box {
$output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal,$noedit);
} elsif ($action eq 'classlists') {
$output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
+ } elsif ($action eq 'menuitems') {
+ $output .= &print_menuitems('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
}
$output .= '
@@ -722,6 +760,10 @@ sub print_config_box {
$output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
} elsif ($action eq 'bridgetasks') {
$output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
+ } elsif ($action eq 'menuitems') {
+ $output .= &print_menuitems('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
+ } elsif ($action eq 'linkprotection') {
+ $output .= &print_linkprotection($cdom,$settings,\$rowtotal,$crstype,$noedit);
} elsif ($action eq 'other') {
$output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype,$noedit);
}
@@ -734,8 +776,8 @@ sub print_config_box {
}
sub process_changes {
- my ($cdom,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_;
- my %newvalues;
+ my ($cdom,$cnum,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_;
+ my (%newvalues,%courselti,$errors);
if (ref($item) eq 'HASH') {
if (ref($changes) eq 'HASH') {
my @ordered;
@@ -752,6 +794,21 @@ sub process_changes {
}
}
}
+ } elsif ($action eq 'linkprotection') {
+ if (ref($values->{'linkprotection'}) eq 'HASH') {
+ foreach my $id (keys(%{$values->{'linkprotection'}})) {
+ if ($id =~ /^\d+$/) {
+ push(@ordered,$id);
+ unless (ref($values->{'linkprotection'}->{$id}) eq 'HASH') {
+ $courselti{$id} = '';
+ }
+ }
+ }
+ }
+ @ordered = sort { $a <=> $b } @ordered;
+ if (($env{'form.linkprot_add'}) && ($env{'form.linkprot_maxnum'} =~ /^\d+$/)) {
+ push(@ordered,$env{'form.linkprot_maxnum'});
+ }
} elsif (ref($item->{'ordered'}) eq 'ARRAY') {
if ($action eq 'courseinfo') {
my ($can_toggle_cat,$can_categorize) =
@@ -814,6 +871,152 @@ sub process_changes {
$changes->{$ext_entry} = $newvalues{$ext_entry};
}
}
+ } elsif ($action eq 'menuitems') {
+ my (%current,@colls);
+ my $next = 1;
+ if ($values->{'menucollections'}) {
+ foreach my $item (split(/;/,$values->{'menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ unless (grep(/^$num$/,@colls)) {
+ push(@colls,$num);
+ }
+ my @entries = split(/\&/,$value);
+ foreach my $entry (@entries) {
+ my ($name,$fields) = split(/=/,$entry);
+ $current{$num}{$name} = $fields;
+ }
+ }
+ }
+ }
+ if (@colls) {
+ @colls = sort { $a <=> $b } @colls;
+ $next += $colls[-1];
+ }
+ if ($env{'form.menucollections_add'} eq $next) {
+ push(@colls,$next);
+ }
+ my $currdef = $values->{'menudefault'};
+ my $possdef = $env{'form.menudefault'};
+ if (($possdef =~ /^\d+$/) && (grep(/^$possdef$/,@colls))) {
+ if ($currdef ne $possdef) {
+ $changes->{'menudefault'} = $possdef;
+ }
+ } elsif ($currdef) {
+ $changes->{'menudefault'} = '';
+ }
+ my $menucoll;
+ if (@colls) {
+ my ($ordered,$cats) = &menuitems_categories();
+ my %shortcats = &menuitems_abbreviations();
+ foreach my $num (@colls) {
+ my ($entry,%include);
+ map { $include{$_}= 1; } &Apache::loncommon::get_env_multiple('form.menucollections_'.$num);
+ foreach my $item (@{$ordered}) {
+ if ($item eq 'shown') {
+ foreach my $type (@{$cats->{$item}}) {
+ $entry .= $type.'=';
+ if ($include{$type}) {
+ $entry .= 'y';
+ } else {
+ $entry .= 'n';
+ }
+ $entry .= '&';
+ }
+ } else {
+ $entry .= $shortcats{$item}.'=';
+ foreach my $type (@{$cats->{$item}}) {
+ if ($include{$type}) {
+ $entry .= $type.',';
+ }
+ }
+ $entry =~ s/,$//;
+ $entry .= '&';
+ }
+ }
+ $entry =~ s/\&$//;
+ if ($menucoll) {
+ $menucoll .= ';';
+ }
+ $menucoll .= $num.'%'.$entry;
+ }
+ if ($menucoll ne $values->{'menucollections'}) {
+ $changes->{'menucollections'} = $menucoll;
+ }
+ } elsif ($values->{'menucollections'}) {
+ $changes->{'menucollections'} = '';
+ }
+ } elsif ($action eq 'linkprotection') {
+ my %menutitles = <imenu_titles();
+ my (@items,%deletions,%itemids,%haschanges);
+ if ($env{'form.linkprot_add'}) {
+ my $name = $env{'form.linkprot_name_add'};
+ $name =~ s/(`)/'/g;
+ my ($newid,$error) = &get_courselti_id($cdom,$cnum,$name);
+ if ($newid) {
+ $itemids{'add'} = $newid;
+ push(@items,'add');
+ $haschanges{$newid} = 1;
+ } else {
+ $errors .= ''.
+ &mt('Failed to acquire unique ID for link protection').
+ '';
+ }
+ }
+ if (ref($values->{'linkprotection'}) eq 'HASH') {
+ my @todelete = &Apache::loncommon::get_env_multiple('form.linkprot_del');
+ my $maxnum = $env{'form.linkprot_maxnum'};
+ for (my $i=0; $i<=$maxnum; $i++) {
+ my $itemid = $env{'form.linkprot_id_'.$i};
+ $itemid =~ s/\D+//g;
+ if ($itemid) {
+ if (ref($values->{'linkprotection'}->{$itemid}) eq 'HASH') {
+ push(@items,$i);
+ $itemids{$i} = $itemid;
+ if ((@todelete > 0) && (grep(/^$i$/,@todelete))) {
+ $deletions{$itemid} = $values->{'linkprotection'}->{$itemid}->{'name'};
+ }
+ }
+ }
+ }
+ }
+ foreach my $idx (@items) {
+ my $itemid = $itemids{$idx};
+ next unless ($itemid);
+ if (exists($deletions{$itemid})) {
+ $courselti{$itemid} = $deletions{$itemid};
+ $haschanges{$itemid} = 1;
+ next;
+ }
+ my %current;
+ if (ref($values->{'linkprotection'}) eq 'HASH') {
+ if (ref($values->{'linkprotection'}->{$itemid}) eq 'HASH') {
+ foreach my $key (keys(%{$values->{'linkprotection'}->{$itemid}})) {
+ $current{$key} = $values->{'linkprotection'}->{$itemid}->{$key};
+ }
+ }
+ }
+ foreach my $inner ('name','key','secret','lifetime','version') {
+ my $formitem = 'form.linkprot_'.$inner.'_'.$idx;
+ $env{$formitem} =~ s/(`)/'/g;
+ if ($inner eq 'lifetime') {
+ $env{$formitem} =~ s/[^\d.]//g;
+ }
+ unless ($idx eq 'add') {
+ if ($current{$inner} ne $env{$formitem}) {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ if ($env{$formitem} ne '') {
+ $courselti{$itemid}{$inner} = $env{$formitem};
+ }
+ }
+ }
+ if (keys(%haschanges)) {
+ foreach my $entry (keys(%haschanges)) {
+ $changes->{$entry} = $courselti{$entry};
+ }
+ }
} else {
foreach my $entry (@ordered) {
if ($entry eq 'cloners') {
@@ -854,7 +1057,7 @@ sub process_changes {
my $clonedom = $env{'form.cloners_newdom'};
if (&check_clone($clonedom,$disallowed) eq 'ok') {
my $newdom = '*:'.$env{'form.cloners_newdom'};
- if (@clonedoms) {
+ if (@clonedoms) {
if (!grep(/^\Q$newdom\E$/,@clonedoms)) {
$newvalues{$entry} .= ','.$newdom;
}
@@ -943,7 +1146,9 @@ sub process_changes {
$autocoowner = $domconf{'autoenroll'}{'co-owners'};
}
}
- unless ($autocoowner) {
+ if ($autocoowner) {
+ $newvalues{'co-owners'} = $values->{'internal.co-owners'};
+ } else {
my @keepcoowners = &Apache::loncommon::get_env_multiple('form.coowners');
my @pendingcoowners = &Apache::loncommon::get_env_multiple('form.pendingcoowners');
my @invitecoowners = &Apache::loncommon::get_env_multiple('form.invitecoowners');
@@ -988,6 +1193,8 @@ sub process_changes {
if ($pendingcoowners ne '') {
@newpending = @pendingcoown;
}
+ } else {
+ @newcoown = @currcoown;
}
$newvalues{'pendingco-owners'} = join(',',sort(@newpending));
$newvalues{'co-owners'} = join(',',sort(@newcoown));
@@ -1266,7 +1473,51 @@ sub process_changes {
}
}
}
- return;
+ return $errors;
+}
+
+sub get_courselti_id {
+ my ($cdom,$cnum,$name) = @_;
+ # get lock on lti db in course
+ my $lockhash = {
+ lock => $env{'user.name'}.
+ ':'.$env{'user.domain'},
+ };
+ my $tries = 0;
+ my $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);
+ my ($id,$error);
+ while (($gotlock ne 'ok') && ($tries<10)) {
+ $tries ++;
+ sleep (0.1);
+ $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);
+ }
+ if ($gotlock eq 'ok') {
+ my %currids = &Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
+ if ($currids{'lock'}) {
+ delete($currids{'lock'});
+ if (keys(%currids)) {
+ my @curr = sort { $a <=> $b } keys(%currids);
+ if ($curr[-1] =~ /^\d+$/) {
+ $id = 1 + $curr[-1];
+ } else {
+ $id = 1;
+ }
+ } else {
+ $id = 1;
+ }
+ if ($id) {
+ unless (&Apache::lonnet::newput('lti',{ $id => $name },$cdom,$cnum) eq 'ok') {
+ $error = 'nostore';
+ }
+ } else {
+ $error = 'nonumber';
+ }
+ }
+ my $dellockoutcome = &Apache::lonnet::del('lti',['lock'],$cdom,$cnum);
+ } else {
+ $error = 'nolock';
+ }
+ return ($id,$error);
}
sub get_sec_str {
@@ -1311,8 +1562,12 @@ sub check_clone {
sub store_changes {
my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes,$crstype) = @_;
my ($chome,$output);
- my (%storehash,@delkeys,@need_env_update,@oldcloner);
+ my (%storehash,@delkeys,@need_env_update,@oldcloner,%oldlinkprot);
if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) {
+ if (ref($values->{'linkprotection'}) eq 'HASH') {
+ %oldlinkprot = %{$values->{'linkprotection'}};
+ }
+ delete($values->{'linkprotection'});
%storehash = %{$values};
} else {
if ($crstype eq 'Community') {
@@ -1322,6 +1577,20 @@ sub store_changes {
}
return $output;
}
+ my ($numchanges,$skipstore);
+ if (ref($changes) eq 'HASH') {
+ $numchanges = scalar(keys(%{$changes}));
+ if (($numchanges == 1) && (exists($changes->{'linkprotection'}))) {
+ $skipstore = 1;
+ } elsif (!$numchanges) {
+ if ($crstype eq 'Community') {
+ $output = &mt('No changes made to community settings.');
+ } else {
+ $output = &mt('No changes made to course settings.');
+ }
+ return $output;
+ }
+ }
my %yesno = (
hidefromcat => '1',
problem_stream_switch => '1',
@@ -1334,7 +1603,7 @@ sub store_changes {
if (grep(/^\Q$item\E$/,@{$actions})) {
$output .= ''.&mt($prefs->{$item}{'text'}).'';
if (ref($changes->{$item}) eq 'HASH') {
- if (keys(%{$changes->{$item}}) > 0) {
+ if ((keys(%{$changes->{$item}}) > 0) || ($item eq 'linkprotection')) {
$output .= &mt('Changes made:').'';
if ($item eq 'other') {
foreach my $key (sort(keys(%{$changes->{$item}}))) {
@@ -1347,6 +1616,41 @@ sub store_changes {
"'$storehash{$key}'")).'';
}
}
+ } elsif ($item eq 'linkprotection') {
+ if (&Apache::lonnet::put('lti',$changes->{'linkprotection'},$cdom,$cnum,1) eq 'ok') {
+ my $hashid=$cdom.'_'.$cnum;
+ &Apache::lonnet::devalidate_cache_new('courselti',$hashid);
+ foreach my $itemid (sort { $a <=> $b } %{$changes->{'linkprotection'}}) {
+ if (ref($changes->{'linkprotection'}->{$itemid}) eq 'HASH') {
+ my %values = %{$changes->{'linkprotection'}->{$itemid}};
+ my %desc = &linkprot_names();
+ my $display;
+ foreach my $title ('name','lifetime','version','key','secret') {
+ if ($title eq 'secret') {
+ my $length = length($values{$title});
+ $display .= $desc{$title}.': '.('*' x $length);
+ } elsif ($title eq 'version') {
+ if ($values{$title} eq 'LTI-1p0') {
+ $display .= $desc{$title}.': 1.1, ';
+ }
+ } else {
+ $display .= $desc{$title}.': '.$values{$title}.', ';
+ }
+ }
+ $output .= '- '.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',''.$itemid.'',
+ "'$display'")).'
';
+ } elsif (ref($oldlinkprot{$itemid}) eq 'HASH') {
+ my $oldname = $oldlinkprot{$itemid}{'name'};
+ $output .= '- '.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',''."$itemid ($oldname)".'')).'
';
+ }
+ }
+ } else {
+ $output .= '- '.
+ ''.
+ &mt('An error occurred when saving changes to link protection settings, which remain unchanged.').
+ ''.
+ '
';
+ }
} else {
if (ref($prefs->{$item}->{'ordered'}) eq 'ARRAY') {
my @settings = @{$prefs->{$item}->{'ordered'}};
@@ -1463,6 +1767,16 @@ sub store_changes {
}
}
$displayname = &mt($text);
+ } elsif ($item eq 'menuitems') {
+ unless ($changes->{$item}{$key} eq '') {
+ if ($key eq 'menudefault') {
+ $displayname = &mt('Default collection of menu items');
+ $displayval = &mt('Collection: [_1]',
+ $changes->{$item}{$key});
+ } elsif ($key eq 'menucollections') {
+ $displayval = &menucollections_display($changes->{$item}{$key});
+ }
+ }
} else {
$displayname = &mt($text);
}
@@ -1475,7 +1789,8 @@ sub store_changes {
$displayval = &Apache::lonlocal::locallocaltime($displayval);
} elsif ($key eq 'categories') {
$displayval = $env{'form.categories_display'};
- } elsif (($key eq 'canuse_pdfforms') || ($key eq 'usejsme') || ($key eq 'uselcmath')) {
+ } elsif (($key eq 'canuse_pdfforms') || ($key eq 'usejsme') ||
+ ($key eq 'uselcmath') || ($key eq 'inline_chem')) {
if ($changes->{$item}{$key} eq '1') {
$displayval = &mt('Yes');
} elsif ($changes->{$item}{$key} eq '0') {
@@ -1525,8 +1840,19 @@ sub store_changes {
}
} elsif ($changes->{$item}{$key} eq '') {
push(@delkeys,$key);
- $output .= '- '.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',
- ''.$displayname.'')).'
';
+ if ($item eq 'menuitems') {
+ if ($key eq 'menudefault') {
+ $output .= '- '.&mt("Default collection of menu items set to: 'Standard' (all menus shown)").'
';
+ } elsif ($key eq 'menucollections') {
+ $output .= '- '.&mt('Specific collections of menus no longer available').'
';
+ }
+ } else {
+ $output .= '- '.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',
+ ''.$displayname.'')).'
';
+ }
+ } elsif ($key eq 'menucollections') {
+ $output .= '- '.&Apache::lonhtmlcommon::confirm_success(&mt('Numbered menu collections:')).'
'.
+ $displayval.' ';
} else {
$output .= '- '.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',
''.$displayname.'',
@@ -1582,6 +1908,9 @@ sub store_changes {
}
}
}
+ if ($skipstore) {
+ return $output;
+ }
if (&Apache::lonnet::put('environment',\%storehash,$cdom,$cnum) eq 'ok') {
if (ref($changes) eq 'HASH') {
if (ref($changes->{'courseinfo'}) eq 'HASH') {
@@ -1752,7 +2081,7 @@ sub get_course {
}
sub get_jscript {
- my ($cid,$cdom,$phase,$crstype,$settings) = @_;
+ my ($cid,$cdom,$phase,$crstype,$settings,$noedit) = @_;
my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype);
my ($jscript,$categorize_js,$loncaparev_js,$instcode_js);
my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript();
@@ -1878,11 +2207,94 @@ function syllabusinfo() {
}
}
ENDSCRIPT
+ my $menuitems_js;
+ unless ($noedit) {
+ my $collections;
+ my $next = 1;
+ if (ref($settings) eq 'HASH') {
+ if ($settings->{'menucollections'} ne '') {
+ my @current;
+ foreach my $item (split(/;/,$settings->{'menucollections'})) {
+ my ($num) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ push(@current,$num);
+ }
+ }
+ $collections = join("','",sort { $a <=> $b } @current);
+ if ($collections) {
+ $collections = "'$collections'";
+ }
+ $next += $current[-1];
+ }
+ }
+ my $deftext = &mt('Standard (all menus shown)');
+ $menuitems_js = <'."\n".
'// '."\n".
+ $syllabus_js."\n".$menuitems_js."\n".'//]]>'."\n".
''."\n".$stubrowse_js."\n";
return $jscript;
}
@@ -3171,7 +3583,7 @@ sub coowner_invitations {
@pendingcoown = split(',',$pendingcoowners);
}
if (ref($currcoownref) eq 'ARRAY') {
- @currcoown == @{$currcoownref};
+ @currcoown = @{$currcoownref};
}
my $disabled;
if ($noedit) {
@@ -3235,7 +3647,7 @@ sub manage_coownership {
@pendingcoown = split(',',$pendingcoowners);
}
if (ref($currcoownref) eq 'ARRAY') {
- @currcoown == @{$currcoownref};
+ @currcoown = @{$currcoownref};
}
my $disabled;
if ($noedit) {
@@ -4016,6 +4428,10 @@ sub print_appearance {
text => ''.&mt($itemtext->{'usejsme'}).'',
input => 'radio',
},
+ 'inline_chem' => {
+ text => ''.&mt($itemtext->{'inline_chem'}).'',
+ input => 'radio',
+ },
);
return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'appearance',$noedit);
}
@@ -4206,6 +4622,364 @@ sub print_bridgetasks {
return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'bridgetasks',$noedit);
}
+sub ltimenu_titles {
+ return &Apache::lonlocal::texthash(
+ fullname => 'Full name',
+ coursetitle => 'Course title',
+ role => 'Role',
+ logout => 'Logout',
+ grades => 'Grades',
+ );
+}
+
+sub print_menuitems {
+ my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype,$noedit) = @_;
+ unless ((ref($settings) eq 'HASH') && (ref($itemtext) eq 'HASH')) {
+ return;
+ }
+ if ($position eq 'top') {
+ my (%defaultmenu_options,@defaultmenu_order,$addcollection);
+ if ($settings->{'menucollections'} ne '') {
+ foreach my $item (split(/;/,$settings->{'menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ $defaultmenu_options{$num} = $num;
+ }
+ }
+ @defaultmenu_order = sort { $a <=> $b } keys(%defaultmenu_options);
+ $addcollection = $defaultmenu_order[-1] + 1;
+ } else {
+ $addcollection = 1;
+ }
+ $defaultmenu_options{$addcollection} = $addcollection;
+ my %items = (
+ 'menudefault' => {
+ text => ''.&mt($itemtext->{'menudefault'}).'
'.
+ &mt("(can be overriden in deep-link context)"),
+ input => 'selectbox',
+ options => \%defaultmenu_options,
+ order => \@defaultmenu_order,
+ nullval => &mt('Standard (all menus shown)'),
+ },
+ );
+ return &make_item_rows($cdom,\%items,['menudefault'],$settings,$rowtotal,$crstype,'menuitems',$noedit);
+ } else {
+ my %menu;
+ my $count = 0;
+ my $next = 1;
+ my ($datatable,$disabled);
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+
+ my ($ordered,$cats) = &menuitems_categories();
+ my @order = @{$ordered};
+ my %categories = %{$cats};
+ my %menutitles = &menuitems_titles();
+ my %menufields = &menuitems_fields();
+
+ if ($settings->{'menucollections'} ne '') {
+ foreach my $item (split(/;/,$settings->{'menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ my @entries = split(/\&/,$value);
+ foreach my $entry (@entries) {
+ my ($name,$fields) = split(/=/,$entry);
+ $menu{$num}{$name} = $fields;
+ }
+ }
+ }
+ if (keys(%menu)) {
+ my @current = sort { $a <=> $b } keys(%menu);
+ $next += $current[-1];
+ foreach my $num (@current) {
+ my %checked;
+ my $on = ' checked="checked"';
+ foreach my $key (keys(%{$menu{$num}})) {
+ if (($key eq 'top') || ($key eq 'inline') || ($key eq 'foot') || ($key eq 'main')) {
+ if ($menu{$num}{$key} eq 'y') {
+ $checked{$key} = $on;
+ }
+ } else {
+ foreach my $field (split(/,/,$menu{$num}{$key})) {
+ if (exists($menufields{$field})) {
+ $checked{$field} = $on;
+ }
+ }
+ }
+ }
+ if (ref($menu{$num}) eq 'HASH') {
+ $datatable .= &item_table_row_start(''.$num.'',$count,'','','','LC_left_item');
+ foreach my $category (@order) {
+ if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
+ $datatable .= '';
+ }
+ }
+ $datatable .= &item_table_row_end();
+ $count ++;
+ }
+ }
+ }
+ } elsif ($noedit) {
+ my $text = &mt('No menu collections defined for this course.');
+ $datatable .= &item_table_row_start($text,$count);
+ }
+ unless ($noedit) {
+ my $add = '';
+ $datatable .= &item_table_row_start($add,$count,'','','','LC_left_item');
+ foreach my $category (@order) {
+ if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
+ $datatable .= '';
+ }
+ }
+ $datatable .= &item_table_row_end();
+ $count ++;
+ }
+ return $datatable;
+ }
+}
+
+sub menuitems_abbreviations {
+ my %briefcats = (
+ text => 'pt',
+ links => 'p',
+ list => 'ps',
+ inline => 's',
+ );
+ return %briefcats;
+}
+
+sub menuitems_categories {
+ my @order = ('shown','text','links','list','inline');
+ my %categories = (
+ shown => ['top','inline','foot','main'],
+ text => ['name','role','crs','disc','fdbk'],
+ links => ['pers','logo','menu','comm','roles','help','logout'],
+ list => ['about','prefs','port','wish','anno','rss'],
+ inline => ['cont','grades','chat','people','groups','resv','syll','feeds'],
+ );
+ return (\@order,\%categories);
+}
+
+sub menuitems_titles {
+ return &Apache::lonlocal::texthash (
+ shown => 'Hierarchy',
+ text => 'Text',
+ links => 'Header links',
+ list => 'Drop-down list',
+ inline => 'Inline links',
+ );
+}
+
+sub menuitems_fields {
+ return &Apache::lonlocal::texthash (
+ top => 'Display header',
+ inline => 'Display inline menu',
+ foot => 'Display footer',
+ main => 'Access to main menu',
+ pers => 'Personal',
+ logo => 'LON-CAPA',
+ menu => 'Home',
+ comm => 'Messages',
+ roles => 'Roles/Courses',
+ help => 'Help',
+ logout => 'Logout',
+ name => 'Fullname',
+ crs => 'Course Title',
+ role => 'Current Role',
+ disc => 'Discussion',
+ fdbk => 'Feedback',
+ about => 'Information',
+ prefs => 'Preferences',
+ port => 'Portfolio',
+ wish => 'Stored Links',
+ anno => 'Calendar',
+ rss => 'RSS Feeds',
+ cont => 'Contents',
+ grades => 'Grades',
+ chat => 'Chat',
+ people => 'People',
+ groups => 'Groups',
+ resv => 'Reservations',
+ syll => 'Syllabus',
+ feeds => 'Feeds',
+ );
+}
+
+sub menucollections_display {
+ my ($collections) = @_;
+ my %menu;
+ my ($ordered,$cats) = &menuitems_categories();
+ my @order = @{$ordered};
+ my %categories = %{$cats};
+ my %menutitles = &menuitems_titles();
+ my %menufields = &menuitems_fields();
+ foreach my $item (split(/;/,$collections)) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ my @entries = split(/\&/,$value);
+ foreach my $entry (@entries) {
+ my ($name,$fields) = split(/=/,$entry);
+ $menu{$num}{$name} = $fields;
+ }
+ }
+ }
+ my $output = '';
+ if (keys(%menu)) {
+ my @current = sort { $a <=> $b } keys(%menu);
+ foreach my $num (@current) {
+ my %checked;
+ foreach my $key (keys(%{$menu{$num}})) {
+ if (($key eq 'top') || ($key eq 'inline') || ($key eq 'foot') || ($key eq 'main')) {
+ if ($menu{$num}{$key} eq 'y') {
+ $checked{$key} = 1;
+ }
+ } else {
+ foreach my $field (split(/,/,$menu{$num}{$key})) {
+ if (exists($menufields{$field})) {
+ $checked{$field} = 1;
+ }
+ }
+ }
+ }
+ if (ref($menu{$num}) eq 'HASH') {
+ $output .= '';
+ }
+ }
+ }
+ return $output;
+}
+
+sub print_linkprotection {
+ my ($cdom,$settings,$rowtotal,$crstype,$noedit) = @_;
+ unless (ref($settings) eq 'HASH') {
+ return;
+ }
+
+ my %linkprotection;
+ my $count = 0;
+ my $next = 1;
+ my ($datatable,$disabled,$css_class);
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+ my %lt = &linkprot_names();
+ my $itemcount = 0;
+
+ if (ref($settings->{'linkprotection'}) eq 'HASH') {
+ if (keys(%{$settings->{'linkprotection'}})) {
+ my @current = sort { $a <=> $b } keys(%{$settings->{'linkprotection'}});
+ $next += $current[-1];
+ for (my $i=0; $i<@current; $i++) {
+ my $num = $current[$i];
+ my %values;
+ if (ref($settings->{'linkprotection'}->{$num}) eq 'HASH') {
+ %values = %{$settings->{'linkprotection'}->{$num}};
+ } else {
+ next;
+ }
+ my $selected;
+ if (($values{'version'} eq 'LTI-1p0') || ($values{'version'} eq '')) {
+ $selected = ' selected="selected"';
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .=
+ ''.
+ ' | '.
+ ''.$lt{'name'}.
+ ': '.
+ (' 'x2).
+ ''.$lt{'version'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'lifetime'}.':'.
+ '
'.
+ ''.$lt{'key'}.
+ ': '.
+ (' 'x2).
+ ''.$lt{'secret'}.':'.
+ ''.
+ ''.
+ ''.
+ ' | ';
+ $itemcount ++;
+ }
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''."\n".
+ ''."\n".
+ ''.&mt('Add').' | '."\n".
+ ''.
+ ''.$lt{'name'}.
+ ': '."\n".
+ (' 'x2).
+ ''.$lt{'version'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'lifetime'}.': '."\n".
+ '
'.
+ ''.$lt{'key'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'secret'}.':'.
+ ' '."\n".
+ ' | ';
+ $$rowtotal ++;
+ return $datatable;;
+}
+
+sub linkprot_names {
+ my %lt = &Apache::lonlocal::texthash(
+ 'version' => 'LTI Version',
+ 'key' => 'Key',
+ 'lifetime' => 'Nonce lifetime (s)',
+ 'name' => 'Launcher Application Name',
+ 'secret' => 'Secret',
+ );
+ return %lt;
+}
+
sub print_other {
my ($cdom,$settings,$allitems,$rowtotal,$crstype,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
@@ -4257,17 +5031,23 @@ sub get_other_items {
}
sub item_table_row_start {
- my ($text,$count,$add_class,$colspan) = @_;
+ my ($text,$count,$add_class,$colspan,$leftclass,$rightclass) = @_;
my $output;
my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row';
$css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
+ if ($leftclass eq '') {
+ $leftclass = 'LC_left_item';
+ }
+ if ($rightclass eq '') {
+ $rightclass = 'LC_right_item';
+ }
$output .= ''."\n".
- ''.$text.
+ ' | '.$text.
' | ';
- if ($colspan) {
- $output .= '';
+ if ($colspan > 1) {
+ $output .= ' | ';
} else {
- $output .= ' | ';
+ $output .= ' | ';
}
return $output;
}
@@ -4308,7 +5088,7 @@ sub yesno_radio {
}
sub select_from_options {
- my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange,$noedit) = @_;
+ my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange,$noedit,$id) = @_;
my $output;
my $disabled;
if ($noedit) {
@@ -4324,6 +5104,9 @@ sub select_from_options {
$output .= ' size="'.$maxsize.'"';
}
}
+ if ($id ne '') {
+ $output .= ' id="'.$id.'"';
+ }
$output .= $disabled.'>'."\n";
if ($nullval ne '') {
$output .= ' | |