--- loncom/interface/lonparmset.pm 2021/01/18 23:11:15 1.522.2.28 +++ loncom/interface/lonparmset.pm 2023/12/29 20:45:18 1.522.2.28.4.11 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set parameters for assessments # -# $Id: lonparmset.pm,v 1.522.2.28 2021/01/18 23:11:15 raeburn Exp $ +# $Id: lonparmset.pm,v 1.522.2.28.4.11 2023/12/29 20:45:18 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -767,7 +767,17 @@ sub valout { } } else { if ($type eq 'date_interval') { - my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($value); + my ($totalsecs,$donesuffix) = split(/_/,$value,2); + my ($usesdone,$donebuttontext,$proctor,$secretkey); + if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) { + $donebuttontext = $1; + (undef,$proctor,$secretkey) = split(/_/,$2); + $usesdone = 'done'; + } elsif ($donesuffix =~ /^done(|_.+)$/) { + $donebuttontext = &mt('Done'); + ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix); + } + my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs); my @timer; $year=$year-70; $mday--; @@ -800,6 +810,13 @@ sub valout { push(@timer,&mt('[quant,_1,sec]',0)); } $result.=join(", ",@timer); + if ($usesdone eq 'done') { + if ($secretkey) { + $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey); + } else { + $result .= ' + "'.$donebuttontext.'"'; + } + } } elsif (&isdateparm($type)) { $result = &Apache::lonlocal::locallocaltime($value). &date_sanity_info($value); @@ -814,11 +831,15 @@ sub valout { sub plink { - my ($type,$dis,$value,$marker,$return,$call)=@_; + my ($type,$dis,$value,$marker,$return,$call,$extra)=@_; my $winvalue=$value; unless ($winvalue) { - if (&isdateparm($type)) { + if ((&isdateparm($type)) || (&is_specialstring($type))) { $winvalue=$env{'form.recent_'.$type}; + } elsif ($type eq 'string_yesno') { + if ($env{'form.recent_string'} =~ /^(yes|no)$/i) { + $winvalue=$env{'form.recent_string'}; + } } else { $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]}; } @@ -829,13 +850,13 @@ sub plink { my $valout = &valout($value,$type,1); my $unencmarker = $marker; foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call, - \$hour, \$min, \$sec) { + \$hour, \$min, \$sec, \$extra) { $$item = &HTML::Entities::encode($$item,'"<>&'); $$item =~ s/\'/\\\'/g; } return '
'. ''. + .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'. $valout.'
'; } @@ -851,20 +872,22 @@ sub page_js { $pjump_def function psub() { + var specstring = /^string_!(yesno|any)/i; if (document.parmform.pres_marker.value!='') { document.parmform.action+='#'+document.parmform.pres_marker.value; var typedef=new Array(); typedef=document.parmform.pres_type.value.split('_'); - if (document.parmform.pres_type.value!='') { - if (typedef[0]=='date') { - eval('document.parmform.recent_'+ - document.parmform.pres_type.value+ - '.value=document.parmform.pres_value.value;'); - } else { - eval('document.parmform.recent_'+typedef[0]+ - '.value=document.parmform.pres_value.value;'); + if (document.parmform.pres_type.value!='') { + if ((typedef[0]=='date') || + (specstring.test(document.parmform.pres_type.value))) { + eval('document.parmform.recent_'+ + document.parmform.pres_type.value+ + '.value=document.parmform.pres_value.value;'); + } else { + eval('document.parmform.recent_'+typedef[0]+ + '.value=document.parmform.pres_value.value;'); + } } - } document.parmform.submit(); } else { document.parmform.pres_value.value=''; @@ -906,6 +929,376 @@ function showHide_courseContent() { COURSECONTENTSCRIPT } +sub validateparms_js { + return <<'ENDSCRIPT'; + +function validateParms() { + var textRegExp = /^settext_/; + var ipRegExp = /^setip/; + var ipallowRegExp = /^setipallow_/; + var ipdenyRegExp = /^setipdeny_/; + var deeplinkRegExp = /^deeplink_/; + var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; + var dlLinkProtectRegExp = /^deeplink_protect_/; + var dlLtidRegExp = /^deeplink_ltid_/; + var dlLticRegExp = /^deeplink_ltic_/; + var dlKeyRegExp = /^deeplink_key_/; + var dlMenusRegExp = /^deeplink_menus_/; + var dlCollsRegExp = /^deeplink_colls_/; + var dlTargetRegExp = /^deeplink_target_/; + var dlExitRegExp = /^deeplink_exit_/; + var dlExitTextRegExp = /^deeplink_exittext_/; + var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/; + var numelements = document.parmform.elements.length; + if ((typeof(numelements) != 'undefined') && (numelements != null)) { + if (numelements) { + for (i=0; i 0) { + var possdeeplink = document.parmform.elements[i].options[idx].value + possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,''); + if (document.parmform.elements['set_'+identifier].value) { + possdeeplink = ','+possdeeplink; + } + document.parmform.elements['set_'+identifier].value += possdeeplink; + } + } else if (dlLinkProtectRegExp.test(name)) { + if (document.parmform.elements[i].checked) { + var identifier = name.replace(dlLinkProtectRegExp,''); + var posslinkurl = document.parmform.elements[i].value; + posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,''); + if (document.parmform.elements['set_'+identifier].value) { + posslinkurl = ','+posslinkurl; + } + document.parmform.elements['set_'+identifier].value += posslinkurl; + } + } else if (dlLtidRegExp.test(name)) { + var identifier = name.replace(dlLtidRegExp,''); + if (isRadioSet('deeplink_protect_'+identifier,'ltid')) { + var possltid = document.parmform.elements[i].value; + possltid = possltid.replace(/\D+/g,''); + if (possltid.length) { + if (document.parmform.elements['set_'+identifier].value) { + possltid = ':'+possltid; + } + document.parmform.elements['set_'+identifier].value += possltid; + } else { + document.parmform.elements['set_'+identifier].value = ''; + alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type."); + return false; + } + } + } else if (dlLticRegExp.test(name)) { + var identifier = name.replace(dlLticRegExp,''); + if (isRadioSet('deeplink_protect_'+identifier,'ltic')) { + var possltic = document.parmform.elements[i].value; + possltic = possltic.replace(/\D+/g,''); + if (possltic.length) { + if (document.parmform.elements['set_'+identifier].value) { + possltic = ':'+possltic; + } + document.parmform.elements['set_'+identifier].value += possltic; + } else { + document.parmform.elements['set_'+identifier].value = ''; + alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type."); + return false; + } + } + } else if (dlKeyRegExp.test(name)) { + var identifier = name.replace(dlKeyRegExp,''); + if (isRadioSet('deeplink_protect_'+identifier,'key')) { + var posskey = document.parmform.elements[i].value; + posskey = posskey.replace(/^\s+|\s+$/g,''); + var origlength = posskey.length; + posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,''); + var newlength = posskey.length; + if (newlength > 0) { + var change = origlength - newlength; + if (change) { + alert(change+' disallowed character(s) removed from deeplink key'); + } + if (document.parmform.elements['set_'+identifier].value) { + posskey = ':'+posskey; + } + document.parmform.elements['set_'+identifier].value += posskey; + } else { + document.parmform.elements['set_'+identifier].value = ''; + if (newlength < origlength) { + alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-"); + } else { + alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key."); + } + return false; + } + } + } else if (dlMenusRegExp.test(name)) { + if (document.parmform.elements[i].checked) { + var identifier = name.replace(dlMenusRegExp,''); + var posslinkmenu = document.parmform.elements[i].value; + posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,''); + if (posslinkmenu == 'std') { + posslinkmenu = '0'; + if (document.parmform.elements['set_'+identifier].value) { + posslinkmenu = ','+posslinkmenu; + } + document.parmform.elements['set_'+identifier].value += posslinkmenu; + } + } + } else if (dlCollsRegExp.test(name)) { + var identifier = name.replace(dlCollsRegExp,''); + if (isRadioSet('deeplink_menus_'+identifier,'colls')) { + var posslinkmenu = document.parmform.elements[i].value; + if (document.parmform.elements['set_'+identifier].value) { + posslinkmenu = ','+posslinkmenu; + } + document.parmform.elements['set_'+identifier].value += posslinkmenu; + } + } else if (dlTargetRegExp.test(name)) { + var identifier = name.replace(dlTargetRegExp,''); + var idx = document.parmform.elements[i].selectedIndex; + if (idx > 0) { + var linktarget = document.parmform.elements[i].options[idx].value + linktarget = linktarget.replace(/^\s+|\s+$/g,''); + if (document.parmform.elements['set_'+identifier].value) { + linktarget = ','+linktarget; + } + document.parmform.elements['set_'+identifier].value += linktarget; + } + } else if (dlExitRegExp.test(name)) { + if (document.parmform.elements[i].checked) { + var identifier = name.replace(dlExitRegExp,''); + var posslinkexit = document.parmform.elements[i].value; + posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,''); + if (document.parmform.elements['set_'+identifier].value) { + posslinkexit = ','+posslinkexit; + } + document.parmform.elements['set_'+identifier].value += posslinkexit; + } + } else if (dlExitTextRegExp.test(name)) { + var identifier = name.replace(dlExitTextRegExp,''); + if ((isRadioSet('deeplink_exit_'+identifier,'yes')) || + (isRadioSet('deeplink_exit_'+identifier,'url'))) { + var posstext = document.parmform.elements[i].value; + posstext = posstext.replace(/^\s+|\s+$/g,''); + var origlength = posstext.length; + posstext = posstext.replace(/[:;'",]/g,''); + var newlength = posstext.length; + if (newlength > 0) { + var change = origlength - newlength; + if (change) { + alert(change+' disallowed character(s) removed from Exit Button text'); + } + if (posstext !== 'Exit Tool') { + posstext = ':'+posstext; + document.parmform.elements['set_'+identifier].value += posstext; + } + } else { + document.parmform.elements['set_'+identifier].value = ''; + if (newlength < origlength) { + alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'"); + } else { + alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use."); + } + return false; + } + } + } + } + } + } + } + return true; +} + +function isRadioSet(name,expected) { + var menuitems = document.getElementsByName(name); + var radioLength = menuitems.length; + result = false; + if (radioLength > 1) { + for (var j=0; j$remove'); + }); + + \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){ + e.preventDefault(); \$(this).closest("div").remove(); + }) +}); + + +END +} + +sub done_proctor_js { + my $defaultdone = &mt('Done'); + &js_escape(\$defaultdone); + return <<"END"; +function toggleSecret(form,radio,key) { + var radios = form[radio+key]; + if (radios.length) { + for (var i=0; i $b } (keys(%lti))) { + if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) { + $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).','; + } + } + $domltistr =~ s/,$//; + if ($domltistr) { + $extra = 'ltid_'.$domltistr; + } + } + my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider'); + if (keys(%courselti)) { + foreach my $item (sort { $a <=> $b } keys(%courselti)) { + if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) { + $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).','; + } + } + $crsltistr =~ s/,$//; + if ($crsltistr) { + if ($extra) { + $extra .= '&'; + } + $extra .= 'ltic_'.$crsltistr; + } + } + if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) { + my @colls; + foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) { + my ($num,$value) = split(/\%/,$item); + if ($num =~ /^\d+$/) { + push(@colls,$num); + } + } + if (@colls) { + if ($extra) { + $extra .= '&'; + } + $extra .= 'menus_'.join(',',@colls); + } + } + } if ($parmlev eq 'general') { if ($uname) { - &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); } elsif ($cgroup) { - &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly); + &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra); } elsif ($csec) { - &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); } else { - &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); } } elsif ($parmlev eq 'map') { if ($uname) { - &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); } elsif ($cgroup) { - &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly); + &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra); } elsif ($csec) { - &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); } else { - &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); } } else { if ($uname) { @@ -1038,32 +1479,32 @@ sub print_row { } } - &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); - &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); - &print_td($r,12,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); - &print_td($r,11,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); - &print_td($r,10,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); + &print_td($r,12,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); + &print_td($r,11,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); + &print_td($r,10,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); if ($csec) { - &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); - &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); - &print_td($r,7,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); + &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); + &print_td($r,7,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); } if ($cgroup) { - &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly); - &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly); - &print_td($r,4,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly); + &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra); + &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra); + &print_td($r,4,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra); } if ($uname) { if ($othergrp) { $r->print($othergrp); } - &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); - &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); - &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly); + &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); + &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); + &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra); } } # end of $parmlev if/else @@ -1083,7 +1524,7 @@ sub print_row { } sub print_td { - my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,$noeditgrp,$readonly)=@_; + my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,$noeditgrp,$readonly,$extra)=@_; $r->print(''); my $nolink = 0; @@ -1111,7 +1552,7 @@ sub print_td { } else { $r->print(&plink($$typeoutpar[$which], $$display{$value},$$outpar[$which], - $mprefix."$which",'parmform.pres','psub')); + $mprefix."$which",'parmform.pres','psub',$extra)); } $r->print(''."\n"); } @@ -1199,23 +1640,27 @@ sub extractResourceInformation { my $srcf=$resource->src(); $srcf=~/\.(\w+)$/; $$typep{$id}=$1; + my $toolsymb; + if ($srcf =~ /ext\.tool$/) { + $toolsymb = $resource->symb(); + } $$keyp{$id}=''; $$uris{$id}=$srcf; - foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys'))) { + foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) { next if ($key!~/^parameter_/); # Hidden parameters - next if (&Apache::lonnet::metadata($srcf,$key.'.hidden') eq 'parm'); + next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm'); # # allparms is a hash of parameter names # - my $name=&Apache::lonnet::metadata($srcf,$key.'.name'); + my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb); if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) { my ($display,$parmdis); $display = &standard_parameter_names($name); if ($display eq '') { - $display= &Apache::lonnet::metadata($srcf,$key.'.display'); + $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb); $parmdis = $display; $parmdis =~ s/\s*\[Part.*$//g; } else { @@ -1224,14 +1669,14 @@ sub extractResourceInformation { $$allparms{$name}=$parmdis; if (ref($defkeytype)) { $$defkeytype{$name}= - &Apache::lonnet::metadata($srcf,$key.'.type'); + &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb); } } # # allparts is a hash of all parts # - my $part= &Apache::lonnet::metadata($srcf,$key.'.part'); + my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb); $$allparts{$part} = &mt('Part: [_1]',$part); # # Remember all keys going with this resource @@ -1277,6 +1722,14 @@ sub isdateparm { return (($type=~/^date/) && (!($type eq 'date_interval'))); } +# Determine if parameter type is specialized string type (i.e., +# not just string or string_yesno. + +sub is_specialstring { + my $type=shift; + return (($type=~/^string_/) && ($type ne 'string_yesno')); +} + # # parmmenu displays a list of the selected parameters. # It also offers a link to show/hide the complete parameter list @@ -1411,6 +1864,7 @@ sub lookUpTableParameter { 'buttonshide' => 'hiding', 'turnoffeditor' => 'hiding', 'encrypturl' => 'hiding', + 'deeplink' => 'hiding', 'randomorder' => 'high_level_randomization', 'randompick' => 'high_level_randomization', 'available' => 'slots', @@ -1426,6 +1880,7 @@ sub lookUpTableParameter { 'lenient' => 'grading', 'retrypartial' => 'tries', 'discussvote' => 'misc', + 'texdisplay' => 'misc', 'examcode' => 'high_level_randomization', ); } @@ -1687,7 +2142,7 @@ function group_or_section(caller) { } if (%grouphash) { - $groups=&mt('Group:').' '). - '" name="recent_'.$_.'" />'); + &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>'). + '" name="recent_'.$item.'" />'); } # ----- Start Parameter Selection - # Hide parm selection? + # Hide parm selection and possibly table? + my ($tablejs,$tabledivsty); + if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) && + ($env{'form.dis'}) && ($pssymb eq '')) { + $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";'; + $tabledivsty = ' style="display:none"'; + } $r->print(< // @@ -2445,7 +2938,7 @@ ENDPARMSELSCRIPT $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel')); &levelmenu($r,\%alllevs,$parmlev); $r->print(&Apache::lonhtmlcommon::row_closure()); - &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp); + &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev); $r->print(&Apache::lonhtmlcommon::row_closure()); $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View'))); &partmenu($r,\%allparts,\@psprt); @@ -2531,6 +3024,7 @@ ENDPARMSELSCRIPT if ($parm_permission->{'edit'}) { undef($readonly); } + $r->print('
'); if ($parmlev eq 'full') { # @@ -2650,20 +3144,24 @@ ENDTABLEHEADFOUR my %type= (); my %default=(); my $uri=&Apache::lonnet::declutter($uris{$rid}); + my $toolsymb; + if ($uri =~ /ext\.tool$/) { + $toolsymb = $symbp{$rid}; + } my $filter=$env{'form.filter'}; foreach (&keysplit($keyp{$rid})) { my $tempkeyp = $_; if (grep $_ eq $tempkeyp, @catmarker) { - my $parmname=&Apache::lonnet::metadata($uri,$_.'.name'); + my $parmname=&Apache::lonnet::metadata($uri,$_.'.name',$toolsymb); # We may only want certain parameters listed if ($filter) { unless ($filter=~/\Q$parmname\E/) { next; } } $name{$_}=$parmname; - $part{$_}=&Apache::lonnet::metadata($uri,$_.'.part'); + $part{$_}=&Apache::lonnet::metadata($uri,$_.'.part',$toolsymb); - my $parmdis=&Apache::lonnet::metadata($uri,$_.'.display'); + my $parmdis=&Apache::lonnet::metadata($uri,$_.'.display',$toolsymb); if ($allparms{$name{$_}} ne '') { my $identifier; if ($parmdis =~ /(\s*\[Part.*)$/) { @@ -2675,9 +3173,9 @@ ENDTABLEHEADFOUR } unless ($display{$_}) { $display{$_}=''; } $display{$_}.=' ('.$name{$_}.')'; - $default{$_}=&Apache::lonnet::metadata($uri,$_); - $type{$_}=&Apache::lonnet::metadata($uri,$_.'.type'); - $thistitle=&Apache::lonnet::metadata($uri,$_.'.title'); + $default{$_}=&Apache::lonnet::metadata($uri,$_,$toolsymb); + $type{$_}=&Apache::lonnet::metadata($uri,$_.'.type',$toolsymb); + $thistitle=&Apache::lonnet::metadata($uri,$_.'.title',$toolsymb); } } my $totalparms=scalar keys %name; @@ -2740,7 +3238,7 @@ ENDTABLEHEADFOUR #-------------------------------------------- for each map, gather information my $mapid; - foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys %maplist) { + foreach $mapid (sort { $a <=> $b } keys(%maplist)) { my $maptitle = $maplist{$mapid}; #----------------------- loop through ids and get all parameter types for map @@ -2762,6 +3260,10 @@ ENDTABLEHEADFOUR if ($map eq $mapid) { my $uri=&Apache::lonnet::declutter($uris{$rid}); + my $toolsymb; + if ($uri =~ /ext\.tool$/) { + $toolsymb = $symbp{$rid}; + } # $r->print("Keys: $keyp{$rid}
\n"); #-------------------------------------------------------------------- @@ -2778,8 +3280,8 @@ ENDTABLEHEADFOUR if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) { $part{$tempkeyp}="0"; - $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name'); - my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display'); + $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb); + my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb); if ($allparms{$name{$tempkeyp}} ne '') { my $identifier; if ($parmdis =~ /(\s*\[Part.*)$/) { @@ -2792,8 +3294,8 @@ ENDTABLEHEADFOUR unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; } $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')'; $display{$tempkeyp} =~ s/_\w+_/_0_/; - $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp); - $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type'); + $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb); + $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb); } } # end loop through keys } @@ -2867,6 +3369,10 @@ ENDTABLEHEADFOUR my $rid = $_; my $uri=&Apache::lonnet::declutter($uris{$rid}); + my $toolsymb; + if ($uri =~ /ext\.tool$/) { + $toolsymb = $symbp{$rid}; + } #-------------------------------------------------------------------- # @catmarker contains list of all possible parameters including part #s @@ -2881,8 +3387,8 @@ ENDTABLEHEADFOUR $tempkeyp =~ s/_\w+_/_0_/; if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) { $part{$tempkeyp}="0"; - $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name'); - my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display'); + $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb); + my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb); if ($allparms{$name{$tempkeyp}} ne '') { my $identifier; if ($parmdis =~ /(\s*\[Part.*)$/) { @@ -2895,8 +3401,8 @@ ENDTABLEHEADFOUR unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; } $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')'; $display{$tempkeyp} =~ s/_\w+_/_0_/; - $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp); - $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type'); + $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb); + $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb); } } # end loop through keys } # end loop through ids @@ -2939,6 +3445,7 @@ ENDMAPONE .'' ); } # end of $parmlev eq general + $r->print('
'); } $r->print(''); $r->print(&Apache::loncommon::end_page()); @@ -3020,20 +3527,39 @@ sub storedata { if ($key =~ /^form\.([a-z]+)\_(.+)$/) { my $cmd=$1; my $thiskey=$2; + next if ($cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink'); my ($tuname,$tudom)=&extractuser($thiskey); my $tkey=$thiskey; if ($tuname) { $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./; } if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') { - my ($data, $typeof, $text, $name, $valchk); + my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch); if ($cmd eq 'set') { $data=$env{$key}; + $valmatch = ''; $valchk = $data; $typeof=$env{'form.typeof_'.$thiskey}; $text = &mt('Saved modified parameter for'); if ($typeof eq 'string_questiontype') { $name = 'type'; + } elsif ($typeof eq 'string_deeplink') { + ($name) = ($typeof =~ /^string_(deeplink)$/); + my $stringmatch = &standard_string_matches($typeof); + if (ref($stringmatch) eq 'ARRAY') { + foreach my $item (@{$stringmatch}) { + if (ref($item) eq 'ARRAY') { + my ($regexpname,$pattern) = @{$item}; + if ($pattern ne '') { + if ($data =~ /$pattern/) { + $valmatch = $regexpname; + $valchk = ''; + last; + } + } + } + } + } } elsif ($typeof eq 'string_lenient') { $name = 'lenient'; } elsif ($typeof eq 'string_discussvote') { @@ -3047,6 +3573,8 @@ sub storedata { if ($thiskey =~ /\.retrypartial$/) { $name = 'retrypartial'; } + } elsif ($typeof eq 'string_tex') { + $name = 'texdisplay'; } } elsif ($cmd eq 'datepointer') { $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key}); @@ -3178,7 +3706,7 @@ sub parse_listdata_key { } sub listdata { - my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_; + my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev)=@_; # Start list output my $oldsection=''; @@ -3290,6 +3818,7 @@ sub listdata { $realm=''.&mt('Folder/Map').': '.&Apache::lonnet::gettitle($1).'
('.$1.')
'; } elsif ($middle) { my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle); + next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview')); $realm=''.&mt('Resource').': '.&Apache::lonnet::gettitle($middle).'
('.$url.' in '.$map.' id: '.$id.')
'; } if ($sortorder eq 'realmstudent') { @@ -3360,7 +3889,7 @@ sub listdata { ); } } elsif ($thistype eq 'date_interval') { - $r->print(&date_interval_selector($thiskey, + $r->print(&date_interval_selector($thiskey,$name, $$resourcedata{$thiskey},$readonly)); } elsif ($thistype =~ m/^string/) { if ($name eq 'availablestudent') { @@ -3383,8 +3912,9 @@ sub listdata { sub date_interval_selector { - my ($thiskey, $showval, $readonly) = @_; - my $result; + my ($thiskey, $pname, $showval, $readonly) = @_; + my ($result,%skipval); + my $currval = $showval; foreach my $which (['days', 86400, 31], ['hours', 3600, 23], ['minutes', 60, 59], @@ -3394,10 +3924,62 @@ sub date_interval_selector { $showval %= $factor; my %select = ((map {$_ => $_} (0..$max)), 'select_form_order' => [0..$max]); + if ($currval eq '') { + unshift(@{$select{'select_form_order'}},''); + $select{''} = ''; + $amount = ''; + } $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey, \%select,'',$readonly); $result .= ' '.&mt($name); } + if ($pname eq 'interval') { + unless ($skipval{'done'}) { + my $checkedon = ''; + my $checkedoff = ''; + my $checkedproc = ''; + my $currproctorkey = ''; + my $currprocdisplay = 'hidden'; + my $currdonetext = &mt('Done'); + my $checkedoff = ' checked="checked"'; + if ($currval =~ /^(?:\d+)_done$/) { + $checkedon = ' checked="checked"'; + } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) { + $currdonetext = $1; + $checkedon = ' checked="checked"'; + } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) { + $currproctorkey = $1; + $checkedproc = ' checked="checked"'; + $currprocdisplay = 'text'; + } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) { + $currdonetext = $1; + $currproctorkey = $2; + $checkedproc = ' checked="checked"'; + $currprocdisplay = 'text'; + } elsif ($currval ne '') { + $checkedoff = ' checked="checked"'; + } else { + $currdonetext = ''; + } + my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"'; + my $disabled; + if ($readonly) { + $disabled = ' disabled="disabled"'; + } + $result .= '
'.&mt('Include "done" button'). + ''.(' 'x2). + ''.(' 'x2). + ''. + '&').'"'.$disabled.' />
'. + ''.&mt('Button text').': '. + '&').'"'.$disabled.' />'; + } + } unless ($readonly) { $result .= ''; } @@ -3408,15 +3990,36 @@ sub date_interval_selector { sub get_date_interval_from_form { my ($key) = @_; my $seconds = 0; + my $numnotnull = 0; foreach my $which (['days', 86400], ['hours', 3600], ['minutes', 60], ['seconds', 1]) { my ($name, $factor) = @{ $which }; if (defined($env{'form.'.$name.'_'.$key})) { - $seconds += $env{'form.'.$name.'_'.$key} * $factor; + unless ($env{'form.'.$name.'_'.$key} eq '') { + $numnotnull ++; + $seconds += $env{'form.'.$name.'_'.$key} * $factor; + } + } } + if (($key =~ /\.interval$/) && + (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) { + if ($env{'form.done_'.$key.'_buttontext'}) { + $env{'form.done_'.$key.'_buttontext'} =~ s/\://g; + $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':'; + if ($env{'form.done_'.$key} eq '_done_proctor') { + $seconds .= '_proctor'; + } + } else { + $seconds .= $env{'form.done_'.$key}; + } + if (($env{'form.done_'.$key} eq '_done_proctor') && + ($env{'form.done_'.$key.'_proctorkey'})) { + $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'}; + } } + return if (!$numnotnull); return $seconds; } @@ -3430,6 +4033,320 @@ sub default_selector { return ''; } +sub string_ip_selector { + my ($thiskey, $showval, $readonly) = @_; + my %access = ( + allow => [], + deny => [], + ); + if ($showval ne '') { + my @current; + if ($showval =~ /,/) { + @current = split(/,/,$showval); + } else { + @current = ($showval); + } + foreach my $item (@current) { + if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) { + push(@{$access{'deny'}},$1); + } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) { + push(@{$access{'allow'}},$item); + } + } + } + if (!@{$access{'allow'}}) { + @{$access{'allow'}} = (''); + } + if (!@{$access{'deny'}}) { + @{$access{'deny'}} = (''); + } + my ($disabled,$addmore); + if ($readonly) { + $disabled=' disabled="disabled"'; + } else { + $addmore = "\n".''; + } + my $output = ' +'; + foreach my $acctype ('allow','deny') { + $output .= ' +'; + } + $output .= ' + +
'.&mt('Allow from').''.&mt('Deny from').'
+
+
'."\n"; + my $num = 0; + foreach my $curr (@{$access{$acctype}}) { + $output .= '
'; + if ($num > 0) { + $output .= ''.&mt('Remove').''; + } + $output .= '
'."\n"; + $num ++; + } + $output .= ' +
'.$addmore.' +
+
'."\n"; + return $output; +} + +sub string_deeplink_selector { + my ($thiskey, $showval, $readonly) = @_; + my (@tables,%values,@current,%titles,%options,%optiontext,%defaults, + %selectnull,%domlti,%crslti,@possmenus,%components); + @tables = ('upper','lower'); + %components = ( + upper => ['state','others','listing','scope'], + lower => ['protect','menus','target','exit'], + ); + %titles = &Apache::lonlocal::texthash ( + state => 'Access status', + others => 'Hide other resources', + listing => 'In Contents and/or Gradebook', + scope => 'Access scope for link', + protect => 'Link protection', + menus => 'Menu Items Displayed', + target => 'Embedded?', + exit => 'Exit Tool Button?', + ); + %options = ( + state => ['only','off','both'], + others => ['hide','unhide'], + listing => ['full','absent','grades','details','datestatus'], + scope => ['res','map','rec'], + protect => ['none','key','ltid','ltic'], + menus => ['std','colls'], + target => ['_self','_top'], + exit => ['no','yes','url'], + ); + %optiontext = &Apache::lonlocal::texthash ( + only => 'deep only', + off => 'deeplink off', + both => 'regular + deep', + hide => 'Hidden', + unhide => 'Unhidden', + full => 'Listed (linked) in both', + absent => 'Not listed', + grades => 'Listed in grades only', + details => 'Listed (unlinked) in both', + datestatus => 'Listed (unlinked) inc. status in both', + res => 'resource only', + map => 'enclosing map/folder', + rec => 'recursive map/folder', + none => 'not in use', + key => 'key access', + ltic => 'LTI access (course)', + ltid => 'LTI access (domain)' , + std => 'Standard (all menus)', + colls => 'Numbered collection', + _self => 'Embedded', + _top => 'Not embedded', + no => 'Not in use', + yes => 'In use, no URL redirect', + url => 'In use, redirect to URL', + ); + %selectnull = &Apache::lonlocal::texthash ( + ltic => 'Select Launcher', + ltid => 'Select Launcher', + colls => 'Select', + ); + if ($showval =~ /,/) { + %values=(); + @current = split(/,/,$showval); + ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/); + ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/); + ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/); + ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/); + ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/); + ($values{'menus'}) = ($current[5] =~ /^(\d+)$/); + ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/); + ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/); + } else { + $defaults{'state'} = 'off', + $defaults{'others'} = 'unhide', + $defaults{'listing'} = 'full'; + $defaults{'scope'} = 'res'; + $defaults{'protect'} = 'none'; + $defaults{'menus'} = '0'; + $defaults{'target'} = '_top'; + $defaults{'exit'} = 'yes'; + } + my $disabled; + if ($readonly) { + $disabled=' disabled="disabled"'; + } + my %courselti = + &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'}, + $env{'course.'.$env{'request.course.id'}.'.domain'}, + 'provider'); + foreach my $item (keys(%courselti)) { + if (ref($courselti{$item}) eq 'HASH') { + $crslti{$item} = $courselti{$item}{'name'}; + } + } + my %lti = + &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'}, + 'linkprot'); + foreach my $item (keys(%lti)) { + if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) { + $domlti{$item} = $lti{$item}{'name'}; + } + } + if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) { + foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) { + my ($num,$value) = split(/\%/,$item); + if ($num =~ /^\d+$/) { + push(@possmenus,$num); + } + } + } + + my $output = ''; + foreach my $table ('upper','lower') { + next unless (ref($components{$table}) eq 'ARRAY'); + $output .= ''; + foreach my $item (@{$components{$table}}) { + $output .= ''; + } + $output .= ''; + foreach my $item (@{$components{$table}}) { + $output .= ''; + } + $output .= '
'.$titles{$item}.'
'; + if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) { + my $selected = $values{$item}; + foreach my $option (@{$options{$item}}) { + if ($item eq 'protect') { + if ($option eq 'ltid') { + next unless (keys(%domlti)); + } elsif ($option eq 'ltic') { + next unless (keys(%crslti)); + } + } elsif (($item eq 'menus') && ($option eq 'colls')) { + next unless (@possmenus); + } + my $checked; + if ($item eq 'menus') { + if (($selected =~ /^\d+$/) && (@possmenus) && + (grep(/^\Q$selected\E$/,@possmenus))) { + if ($option eq 'colls') { + $checked = ' checked="checked"'; + } + } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) { + $checked = ' checked="checked"'; + } + } elsif ($selected =~ /^\Q$option\E/) { + $checked = ' checked="checked"'; + } + my $onclick; + unless ($readonly) { + my $esc_key = &js_escape($thiskey); + $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"'; + } + $output .= ''; + if (($item eq 'protect') && ($option eq 'key')) { + my $visibility="hidden"; + my $currkey; + if ($checked) { + $visibility = "text"; + $currkey = (split(/\:/,$values{$item}))[1]; + } + $output .= ' '. + ''; + } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) { + my $display="none"; + my ($current,$blankcheck,@possibles); + if ($checked) { + $display = 'inline-block'; + if (($option eq 'ltic') || ($option eq 'ltid')) { + $current = (split(/\:/,$selected))[1]; + } else { + $current = $selected; + } + } else { + $blankcheck = ' selected="selected"'; + } + if ($option eq 'ltid') { + @possibles = keys(%domlti); + } elsif ($option eq 'ltic') { + @possibles = keys(%crslti); + } else { + @possibles = @possmenus; + } + $output .= '
 
'; + } + $output .= '
'; + } + if ($item eq 'exit') { + my $exitsty = 'none'; + my $displayval; + if ($values{$item} =~ /^(yes|url)/) { + $exitsty = 'inline-block'; + my $currval = (split(/\:/,$values{$item}))[1]; + if ($currval eq '') { + $displayval = 'Exit Tool'; + } else { + $displayval = $currval; + } + } + $output .= '

'.&mt('Button text').': '. + '
'; + } + } else { + my $selected = $values{$item}; + my $defsel; + if ($selected eq '') { + $defsel = ' selected="selected"'; + } + $output .= ''; + } + $output .= '
'."\n"; + if ($table eq 'upper') { + $output .= '
'; + } + } + return $output; +} + +{ + my %strings = ( 'string_yesno' @@ -3457,8 +4374,35 @@ my %strings = => [['yes','Yes'], ['notended','Yes, unless discussion ended'], ['no','No']], + 'string_ip' + => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'], + ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], + 'string_deeplink' + => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']], + 'string_tex' + => [['tth', 'tth (TeX to HTML)'], + ['mathjax', 'MathJax']], ); +my %stringmatches = ( + 'string_ip' + => [['_allowfrom_','[^\!]+'], + ['_denyfrom_','\!']], + 'string_deeplink' + => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']], + ); + +my %stringtypes = ( + type => 'string_questiontype', + lenient => 'string_lenient', + retrypartial => 'string_yesno', + discussvote => 'string_discussvote', + examcode => 'string_examcode', + acc => 'string_ip', + deeplink => 'string_deeplink', + texdisplay => 'string_tex', + ); + sub standard_string_options { my ($string_type) = @_; if (ref($strings{$string_type}) eq 'ARRAY') { @@ -3467,6 +4411,14 @@ sub standard_string_options { return; } +sub standard_string_matches { + my ($string_type) = @_; + if (ref($stringmatches{$string_type}) eq 'ARRAY') { + return $stringmatches{$string_type}; + } + return; +} + sub string_selector { my ($thistype, $thiskey, $showval, $name, $readonly) = @_; @@ -3497,6 +4449,12 @@ sub string_selector { } } } + + if ($thistype eq 'string_ip') { + return &string_ip_selector($thiskey,$showval,$readonly); + } elsif ($thistype eq 'string_deeplink') { + return &string_deeplink_selector($thiskey,$showval,$readonly); + } my ($result,$disabled); @@ -3551,6 +4509,55 @@ sub string_selector { return $result; } +sub oldversion_warning { + my ($name,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_; + my $desc; + my %stringtypes = ( + type => 'string_questiontype', + lenient => 'string_lenient', + retrypartial => 'string_yesno', + discussvote => 'string_discussvote', + examcode => 'string_examcode', + ); + if (exists($stringtypes{$name})) { + if ($name eq 'examcode') { + $desc = $value; + } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') { + foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) { + next unless (ref($possibilities) eq 'ARRAY'); + my ($parmval, $description) = @{ $possibilities }; + if ($parmval eq $value) { + $desc = $description; + last; + } + } + } + } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) { + my $now = time; + if ($value =~ /^\d+$/) { + if ($name eq 'printstartdate') { + if ($value > $now) { + $desc = &Apache::lonlocal::locallocaltime($value); + } + } elsif ($name eq 'printenddate') { + if ($value < $now) { + $desc = &Apache::lonlocal::locallocaltime($value); + } + } + } + } + my $standard_name = &standard_parameter_names($name); + return '

'. + &mt('[_1] was [_2]not[_3] set to [_4].', + $standard_name,'','','"'.$desc.'"').'
'. + &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).', + $cmajor.'.'.$cminor,$chostname, + $needsrelease). + '

'; +} + +} + # # Shift all start and end dates by $shift # @@ -3624,6 +4631,10 @@ sub newoverview { '. &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n". &showhide_js()."\n". + &validateparms_js()."\n". + &ipacc_boxes_js()."\n". + &done_proctor_js()."\n". + &deeplink_js()."\n". '// ]]> '; @@ -3632,7 +4643,7 @@ sub newoverview { my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview'); $r->print($start_page.$breadcrumbs); $r->print(< +
ENDOVER my @ids=(); my %typep=(); @@ -3698,10 +4709,8 @@ ENDOVER $r->print('
'); $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel')); &levelmenu($r,\%alllevs,$parmlev); - if ($parmlev ne 'general') { - $r->print(&Apache::lonhtmlcommon::row_closure()); - &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp); - } + $r->print(&Apache::lonhtmlcommon::row_closure()); + &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev); $r->print(&Apache::lonhtmlcommon::row_closure(1)); $r->print(&Apache::lonhtmlcommon::end_pick_box()); $r->print('
'); @@ -3764,7 +4773,7 @@ ENDOVER # List data - &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly); + &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev); } $r->print(&tableend()); unless ($readonly) { @@ -3813,16 +4822,25 @@ sub overview { my ($r,$parm_permission) = @_; my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $crs = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'}; + my $js = ''."\n"; my $readonly = 1; if ($parm_permission->{'edit'}) { undef($readonly); } &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview', text=>"Overview Mode"}); - my $start_page=&Apache::loncommon::start_page('Modify Parameters'); + my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js); my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview'); $r->print($start_page.$breadcrumbs); - $r->print(''); + $r->print(''); # Store modified unless ($readonly) { @@ -4929,7 +5947,11 @@ sub parm_change_log { $parmitem = &mt($parmitem); $output .= &mt('Type: [_1]',$parmitem); } else { - my ($level,@all)=&parmval_by_symb($what,$middle,&Apache::lonnet::metadata($middle,$what), + my $toolsymb; + if ($middle =~ /ext\.tool$/) { + $toolsymb = $middle; + } + my ($level,@all)=&parmval_by_symb($what,$middle,&Apache::lonnet::metadata($middle,$what,$toolsymb), $uname,$udom,$issection,$issection,$courseopt); my $showvalue = $value; if ($istype{$parmname} eq '') { @@ -5117,53 +6139,6 @@ sub parameter_releasecheck { return $needsnewer; } -sub oldversion_warning { - my ($name,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_; - my $desc; - my %stringtypes = ( - type => 'string_questiontype', - lenient => 'string_lenient', - retrypartial => 'string_yesno', - discussvote => 'string_discussvote', - examcode => 'string_examcode', - ); - if (exists($stringtypes{$name})) { - if ($name eq 'examcode') { - $desc = $value; - } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') { - foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) { - next unless (ref($possibilities) eq 'ARRAY'); - my ($parmval, $description) = @{ $possibilities }; - if ($parmval eq $value) { - $desc = $description; - last; - } - } - } - } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) { - my $now = time; - if ($value =~ /^\d+$/) { - if ($name eq 'printstartdate') { - if ($value > $now) { - $desc = &Apache::lonlocal::locallocaltime($value); - } - } elsif ($name eq 'printenddate') { - if ($value < $now) { - $desc = &Apache::lonlocal::locallocaltime($value); - } - } - } - } - my $standard_name = &standard_parameter_names($name); - return '

'. - &mt('[_1] was [_2]not[_3] set to [_4].', - $standard_name,'','','"'.$desc.'"').'
'. - &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).', - $cmajor.'.'.$cminor,$chostname, - $needsrelease). - '

'; -} - sub get_permission { my %permission; my $allowed = 0;