[LON-CAPA-cvs] cvs: rat /client parameter.html loncom/interface lonparmset.pm loncom/misc releaseslist.xml

raeburn raeburn at source.lon-capa.org
Sun Jan 6 10:27:57 EST 2019


raeburn		Sun Jan  6 15:27:57 2019 EDT

  Modified files:              
    /loncom/interface	lonparmset.pm 
    /loncom/misc	releaseslist.xml 
    /rat/client	parameter.html 
  Log:
  - Bug 6400
    - deeplink parameter incorporates three components: 
      (a) In Contents or Gradebook?, (b) Access scope via deep-link,
      (c) Supported Link Types.
    - Allowed values for (a) 'full','absent','grades','details','datestatus'
    - Allowed values for (b) 'res','map','rec
    - Allowed values for (c) 'any','only','key','lti' 
      - In the case of key, append ':key value (alphanumeric characters)
      - In the case of lti, append :num, where num is the internal number of 
        the LTI Consumer, from the Domain Configuration for "LTI Provider" 
        (User's identity sent is set to "No" for this type of LTI use case). 
  
  
-------------- next part --------------
Index: loncom/interface/lonparmset.pm
diff -u loncom/interface/lonparmset.pm:1.587 loncom/interface/lonparmset.pm:1.588
--- loncom/interface/lonparmset.pm:1.587	Tue Nov 13 03:59:00 2018
+++ loncom/interface/lonparmset.pm	Sun Jan  6 15:27:48 2019
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set parameters for assessments
 #
-# $Id: lonparmset.pm,v 1.587 2018/11/13 03:59:00 raeburn Exp $
+# $Id: lonparmset.pm,v 1.588 2019/01/06 15:27:48 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -1065,9 +1065,10 @@
 # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
 # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
 # @param {string} $call - javascript function to call to submit the form ('psub')
-# @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive. 
+# @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
+# @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
 sub plink {
-    my ($type,$dis,$value,$marker,$return,$call,$recursive)=@_;
+    my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
     my $winvalue=$value;
     unless ($winvalue) {
         if (&isdateparm($type)) {
@@ -1082,13 +1083,13 @@
     my $valout = &valout($value,$type,$parmname,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 '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
-        .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."'".');">'.
+        .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                                               &mt('recursive').'</td></tr>' : '').'</table>';
 
@@ -1237,12 +1238,16 @@
     var patternLenientStd = /^(yes|no|default)$/;
     var ipallowRegExp = /^setipallow_/;
     var ipdenyRegExp = /^setipdeny_/; 
+    var deeplinkRegExp = /^deeplink_(listing|scope)_/;
+    var deeplinkUrlsRegExp = /^deeplink_urls_/;
+    var deeplinkltiRegExp = /^deeplink_lti_/;
+    var deeplinkkeyRegExp = /^deeplink_key_/;
     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
         if (document.parmform.elements.length) {
             for (i=0; i<document.parmform.elements.length; i++) {
                 var name=document.parmform.elements[i].name;
-                if (textRegExp.test(name)) { 
+                if (textRegExp.test(name)) {
                     var identifier = name.replace(textRegExp,'');
                     if (tailLenient.test(identifier)) {
                         if (document.parmform.elements['set_'+identifier].length) {
@@ -1265,31 +1270,61 @@
                             }
                         }
                     }
-                } else {
-                    if (ipallowRegExp.test(name)) {
-                        var identifier = name.replace(ipallowRegExp,'');
-                        var possallow = document.parmform.elements[i].value;
-                        possallow = possallow.replace(/^\s+|\s+$/g,'');
-                        if (patternIP.test(possallow)) {
-                            if (document.parmform.elements['set_'+identifier].value) {
-                                possallow = ','+possallow;
-                            }
-                            document.parmform.elements['set_'+identifier].value += possallow; 
-                        }
-                    } else {
-                        if (ipdenyRegExp.test(name)) {
-                            var identifier = name.replace(ipdenyRegExp,'');
-                            var possdeny = document.parmform.elements[i].value;
-                            possdeny = possdeny.replace(/^\s+|\s+$/g,'');
-                            if (patternIP.test(possdeny)) {
-                                possdeny = '!'+possdeny;
-                                if (document.parmform.elements['set_'+identifier].value) {
-                                    possdeny = ','+possdeny;
-                                }
-                                document.parmform.elements['set_'+identifier].value += possdeny;
-                            }
-                        }
+                } else if (ipallowRegExp.test(name)) {
+                    var identifier = name.replace(ipallowRegExp,'');
+                    var possallow = document.parmform.elements[i].value;
+                    possallow = possallow.replace(/^\s+|\s+$/g,'');
+                    if (patternIP.test(possallow)) {
+                        if (document.parmform.elements['set_'+identifier].value) {
+                            possallow = ','+possallow;
+                        }
+                        document.parmform.elements['set_'+identifier].value += possallow;
+                    }
+                } else if (ipdenyRegExp.test(name)) {
+                    var identifier = name.replace(ipdenyRegExp,'');
+                    var possdeny = document.parmform.elements[i].value;
+                    possdeny = possdeny.replace(/^\s+|\s+$/g,'');
+                    if (patternIP.test(possdeny)) {
+                        possdeny = '!'+possdeny;
+                        if (document.parmform.elements['set_'+identifier].value) {
+                            possdeny = ','+possdeny;
+                        }
+                        document.parmform.elements['set_'+identifier].value += possdeny;
+                    }
+                } else if (deeplinkRegExp.test(name)) {
+                    var identifier =  name.replace(deeplinkRegExp,'');
+                    var possdeeplink = document.parmform.elements[i].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 (deeplinkUrlsRegExp.test(name)) {
+                    if (document.parmform.elements[i].checked) {
+                        var identifier =  name.replace(deeplinkUrlsRegExp,'');
+                        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 (deeplinkltiRegExp.test(name)) {
+                    var identifier = name.replace(deeplinkltiRegExp,'');
+                    var posslti = document.parmform.elements[i].value;
+                    posslti = posslti.replace(/\D+/g,'');
+                    if (document.parmform.elements['set_'+identifier].value) {
+                        posslti = ':'+posslti;
+                    }
+                    document.parmform.elements['set_'+identifier].value += posslti;
+                } else if (deeplinkkeyRegExp.test(name)) {
+                    var identifier = name.replace(deeplinkkeyRegExp,'');
+                    var posskey = document.parmform.elements[i].value;
+                    posskey = posskey.replace(/\W+/g,'');
+                    if (document.parmform.elements['set_'+identifier].value) {
+                        posslti = ':'+posskey;
                     }
+                    document.parmform.elements['set_'+identifier].value += posskey;
                 }
             }
         }
@@ -1351,6 +1386,45 @@
 
 }
 
+# Javascript function toggle
+sub deeplink_js {
+    return <<"END";
+function toggleDeepLink(form,item,key) {
+    var radios = form['deeplink_'+item+'_'+key];
+    if (radios.length) {
+        var keybox;
+        if (document.getElementById('deeplink_key_'+item+'_'+key)) {
+            keybox = document.getElementById('deeplink_key_'+item+'_'+key);
+        }
+        var ltidiv;
+        if (document.getElementById('deeplinkdiv_lti_'+item+'_'+key)) {
+            ltidiv = document.getElementById('deeplinkdiv_lti_'+item+'_'+key);
+        }
+        for (var i=0; i<radios.length; i++) {
+            if (radios[i].checked) {
+                if (radios[i].value == 'lti') {
+                    ltidiv.style.display = 'inline-block';
+                    keybox.type = 'hidden';
+                    keybox.value = '';
+                } else {
+                    if (ltidiv != '') {
+                        ltidiv.style.display = 'none';
+                        form['deeplink_lti_'+key].selectedIndex = 0;
+                    }
+                    if (radios[i].value == 'key') {
+                        keybox.type = 'text';
+                    } else {
+                        keybox.type = 'hidden';
+                    }
+                }
+            }
+        }
+    }
+}
+END
+
+}
+
 # Prints HTML page start for table mode.
 # @param {Apache2::RequestRec} $r - the Apache request
 # @param {string} $psymb - resource symb
@@ -1477,7 +1551,7 @@
     my $mprefix=$rid.'&'.$thismarker.'&';
     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
-        $eff_groupparm,$recurse_check,$recursinfo);
+        $eff_groupparm,$recurse_check,$recursinfo,$extra);
     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
         if ($result eq '') {
             $recurse_check = 1;
@@ -1535,25 +1609,45 @@
         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
         $effparm_rec = 1;
     }
+    if ($parmname eq 'deeplink') {
+        my %posslti;
+        my %lti =
+            &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
+                                            'provider');
+        foreach my $item (keys(%lti)) {
+            if (ref($lti{$item}) eq 'HASH') {
+                unless ($lti{$item}{'requser'}) {
+                    $posslti{$item} = $lti{$item}{'consumer'};
+                }
+            }
+        }
+        if (keys(%posslti)) {
+            $extra = 'lti_';
+            foreach my $lti (sort { $a <=> $b } keys(%posslti)) {
+                $extra .= $lti.':'.&js_escape($posslti{$lti}).',';
+            }
+            $extra =~ s/,$//;
+        }
+    }
     if ($parmlev eq 'general') {
         if ($uname) {
-            &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
+            &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
         } elsif ($cgroup) {
-            &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
+            &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
         } elsif ($csec) {
-            &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
+            &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
         } else {
-            &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
+            &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
         }
     } elsif ($parmlev eq 'map') {
         if ($uname) {
-            &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1); 
+            &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
         } elsif ($cgroup) {
-            &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1);
+            &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
         } elsif ($csec) {
-            &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
+            &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
         } else {
-            &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
+            &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
         }
     } else {
         if ($uname) {
@@ -1576,31 +1670,31 @@
             }
         }
 
-        &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
-        &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
-        &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
-        &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
-        &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
+        &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
+        &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
+        &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
+        &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
+        &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
 
         if ($csec) {
-            &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
-            &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
-            &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
+            &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
+            &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
+            &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
         }
 
         if ($cgroup) {
-            &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
-            &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1);
-            &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly);
+            &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
+            &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
+            &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
         }
 
         if ($uname) {
             if ($othergrp) {
                 $r->print($othergrp);
             }
-            &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
-            &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
-            &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
+            &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
+            &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
+            &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
         }
     } # end of $parmlev if/else
     if (ref($recursinfo) eq 'ARRAY') {
@@ -1666,10 +1760,11 @@
 # @param {hash reference} $display - parameter key -> full title for the parameter
 # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
 # @param {boolean} $readonly -true if editing not allowed.
-# @param {boolean} $ismaplevel - true if level is for a map. 
+# @param {boolean} $ismaplevel - true if level is for a map.
+# @param {strring} $extra - extra informatio to pass to plink.
 sub print_td {
     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
-        $noeditgrp,$readonly,$ismaplevel)=@_;
+        $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
     $ineffect = 0;
     $currval = $$outpar[$which];
@@ -1723,7 +1818,8 @@
     } else {
         $r->print(&plink($currtype,
                          $$display{$value},$currval,
-                         $mprefix.$currlevel,'parmform.pres','psub',$recursive));
+                         $mprefix.$currlevel,'parmform.pres','psub',$recursive,
+                         $extra));
     }
     $r->print('</td>'."\n");
 }
@@ -3832,7 +3928,7 @@
 # Stores parameter data, using form parameters directly.
 #
 # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
-# set_* (except settext, setipallow, setipdeny) - set a parameter value
+# set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
 # del_* - remove a parameter
 # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
 # dateinterval_* - set a date interval parameter (value refers to more form parameters)
@@ -3865,7 +3961,7 @@
             my $cmd=$1;
             my $thiskey=$2;
             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
-            next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny');
+            next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
@@ -3896,8 +3992,8 @@
                     $text = &mt('Saved modified parameter for');
                     if ($typeof eq 'string_questiontype') {
                         $name = 'type';
-                    } elsif ($typeof eq 'string_lenient') {
-                        $name = 'lenient';
+                    } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
+                        ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
                         my $stringmatch = &standard_string_matches($typeof);
                         if (ref($stringmatch) eq 'ARRAY') {
                             foreach my $item (@{$stringmatch}) {
@@ -4628,6 +4724,139 @@
     return $output;
 }
 
+sub string_deeplink_selector {
+    my ($thiskey, $showval, $readonly) = @_;
+    my (@components,%values, at current,%titles,%options,%optiontext,%defaults,%posslti);
+    @components = ('listing','scope','urls');
+    %titles = &Apache::lonlocal::texthash (
+                  listing => 'In Contents and/or Gradebook',
+                  scope   => 'Access scope for link',
+                  urls    => 'Supported link types',
+              );
+    %options = (
+                   listing => ['full','absent','grades','details','datestatus'],
+                   scope   => ['res','map','rec'],
+                   urls    => ['any','only','key','lti'],
+               );
+    %optiontext = &Apache::lonlocal::texthash (
+                    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',
+                    any        => 'regular + deep',
+                    only       => 'deep only',
+                    key        => 'deep with key',
+                    lti        => 'deep with LTI launch',
+                  );
+    if ($showval =~ /,/) {
+        @current = split(/,/,$showval);
+        ($values{'listing'}) = ($current[0] =~ /^(full|absent|grades|details|datestatus)$/);
+        ($values{'scope'}) = ($current[1] =~ /^(res|map|rec)$/);
+        ($values{'urls'}) = ($current[2] =~ /^(any|only|key:\w+|lti:\d+)$/);
+    } else {
+        $defaults{'listing'} = 'full';
+        $defaults{'scope'} = 'res';
+        $defaults{'urls'} = 'any';
+    }
+    my $disabled;
+    if ($readonly) {
+        $disabled=' disabled="disabled"';
+    }
+    my %lti = 
+        &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
+                                        'provider');
+    foreach my $item (keys(%lti)) {
+        if (ref($lti{$item}) eq 'HASH') {
+            unless ($lti{$item}{'requser'}) {
+                $posslti{$item} = $lti{$item}{'consumer'};
+            }
+        }
+    }
+    my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
+    foreach my $item ('listing','scope','urls') {
+        $output .= '<th>'.$titles{$item}.'</th>';
+    }
+    $output .= '</tr><tr>';
+    foreach my $item (@components) {
+        $output .= '<td>';
+        if ($item eq 'urls') {
+            my $selected = $values{$item};
+            foreach my $option (@{$options{$item}}) {
+                if ($option eq 'lti') {
+                    next unless (keys(%posslti));
+                }
+                my $checked;
+                if ($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 .= '<span class="LC_nobreak"><label>'.
+                           '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
+                           $optiontext{$option}.'</label>';
+                if ($option eq 'key') {
+                    my $visibility="hidden";
+                    my $currkey;
+                    if ($checked) {
+                        $visibility = "text";
+                        $currkey = (split(/\:/,$values{$item}))[1];
+                    }
+                    $output .= ' '.
+                        '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="6"'.$disabled.' />';
+                } elsif ($option eq 'lti') {
+                    my $display="none";
+                    my ($currlti,$blankcheck);
+                    if ($checked) {
+                        $display = 'inline-block';
+                        $currlti = (split(/\:/,$values{$item}))[1];
+                    } else {
+                        $blankcheck = ' selected="selected"';
+                    }
+                    $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
+                               ' style="display: '.$display.'"> <select name="'.
+                               'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>'.
+                               '<option value=""'.$blankcheck.'>'.&mt('Select Provider').'</option>'."\n";
+                    foreach my $lti (sort { $a <=> $b } keys(%posslti)) {
+                        my $selected;
+                        if ($lti == $currlti) {
+                            $selected = ' selected="selected"';
+                        }
+                        $output .= '<option value="'.$lti.'"'.$selected.'>'.$posslti{$lti}.'</option>';
+                    }
+                    $output .= '</select></div>';
+                }
+                $output .= '</span> ';
+            }
+        } else {
+            my $selected = $values{$item};
+            my $defsel;
+            if ($selected eq '') {
+                $defsel = ' selected="selected"';
+            }
+            $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
+                       '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
+            foreach my $option (@{$options{$item}}) {
+                $output .= '<option value="'.$option.'"';
+                if ($option eq $selected) {
+                    $output .= ' selected="selected"';
+                }
+                $output .= '>'.$optiontext{$option}.'</option>';
+            }
+            $output .= '</select>';
+        }
+        $output .= '</td>';
+    }
+    $output .= '</tr></table>'."\n";
+    return $output;
+}
+
 
 { # block using some constants related to parameter types (overview mode)
 
@@ -4663,11 +4892,7 @@
              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
      'string_deeplink'
-             => [['full','Displayed (linked) in Contents and Grades'],
-                 ['absent','Not displayed in Contents or Grades'],
-                 ['grades','Displayed in Grades only'],
-                 ['details','Displayed (unlinked) in Contents and Grades'],
-                 ['datestatus','Displayed (with status), but unlinked in Contents and Grades']],
+             => [['on','Set choices for link protection, resource listing, and access scope']],
     );
    
 
@@ -4677,6 +4902,8 @@
          'string_ip'
               => [['_allowfrom_','[^\!]+'],
                   ['_denyfrom_','\!']],
+         'string_deeplink'
+              => [['on','^(full|absent|grades|details|datestatus)\,(res|map|rec)\,(any|only|key\:\w+|lti\:\d+)$']],
     );
 
 my %stringtypes = (
@@ -4746,6 +4973,7 @@
             ($thistype eq 'string_lenient') ||
             ($thistype eq 'string_discussvote') ||
             ($thistype eq 'string_ip') ||
+            ($thistype eq 'string_deeplink') ||
             ($name eq 'retrypartial')) {
         my ($got_chostname,$chostname,$cmajor,$cminor); 
         foreach my $possibilities (@{ $strings{$thistype} }) {
@@ -4784,6 +5012,8 @@
 
     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);
@@ -5198,6 +5428,7 @@
             &validateparms_js()."\n".
             &ipacc_boxes_js()."\n".
             &done_proctor_js()."\n".
+            &deeplink_js()."\n".
 '// ]]>
 </script>
 ';
@@ -5419,6 +5650,7 @@
              &validateparms_js()."\n".
              &ipacc_boxes_js()."\n".
              &done_proctor_js()."\n".
+             &deeplink_js()."\n".
              '// ]]>'."\n".
              '</script>'."\n";
     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
Index: loncom/misc/releaseslist.xml
diff -u loncom/misc/releaseslist.xml:1.18 loncom/misc/releaseslist.xml:1.19
--- loncom/misc/releaseslist.xml:1.18	Tue Nov 13 03:59:08 2018
+++ loncom/misc/releaseslist.xml	Sun Jan  6 15:27:53 2019
@@ -24,11 +24,7 @@
 <parameter name="acc" valuematch="_denyfrom_">2.12</parameter>
 <parameter name="interval" valuematch="done">2.12</parameter>
 <parameter name="" namematch="maplevelrecurse" value="">2.12</parameter>
-<parameter name="deeplink" value="full">2.12</parameter>
-<parameter name="deeplink" value="absent">2.12</parameter>
-<parameter name="deeplink" value="grades">2.12</parameter>
-<parameter name="deeplink" value="details">2.12</parameter>
-<parameter name="deeplink" value="datestatus">2.12</parameter>
+<parameter name="deeplink" valuematch="on">2.12</parameter>
 <resourcetag name="responsetype" value="custom">2.1</resourcetag>
 <resourcetag name="responsetype" value="math">2.2</resourcetag>
 <resourcetag name="responsetype" value="functionplot">2.10</resourcetag>
Index: rat/client/parameter.html
diff -u rat/client/parameter.html:1.79 rat/client/parameter.html:1.80
--- rat/client/parameter.html:1.79	Sun Jan  6 04:02:19 2019
+++ rat/client/parameter.html	Sun Jan  6 15:27:57 2019
@@ -5,7 +5,7 @@
 The LearningOnline Network with CAPA
 Parameter Input Window
 //
-// $Id: parameter.html,v 1.79 2019/01/06 04:02:19 raeburn Exp $
+// $Id: parameter.html,v 1.80 2019/01/06 15:27:57 raeburn Exp $
 //
 // Copyright Michigan State University Board of Trustees
 //
@@ -52,6 +52,7 @@
 var pnonreccol='';
 var pmarkerst='';
 var pparm='';
+var pextra='';
 
 var defhour=0;
 var defmin=0;
@@ -412,6 +413,69 @@
     assemble();
 }
 
+function validateDeepLink() {
+    var sform=choices.document.forms.sch;
+    svalue = sform.deeplinklisted.options[sform.deeplinklisted.selectedIndex].value+',';
+    svalue += sform.deeplinkacc.options[sform.deeplinkacc.selectedIndex].value+',';
+    if (sform.deeplinktypes.length) {
+        for (var i=0; i<sform.deeplinktypes.length; i++) {
+            if (sform.deeplinktypes[i].checked) {
+                svalue += sform.deeplinktypes[i].value;
+                if (sform.deeplinktypes[i].value == 'key') {
+                    var posskey = sform.deeplinkkey.value;
+                    posskey = posskey.replace(/^\s+|\s+$/g,'');
+                    var keyRegExp = /^\w+$/;
+                    if (keyRegExp.test(posskey)) {
+                        svalue += ':'+posskey;
+                    }
+                } else if (sform.deeplinktypes[i].value == 'lti') {
+                    var posslti = sform.linkposslti.options[sform.linkposslti.selectedIndex].value;
+                    if (posslti != '' && posslti != null) {
+                        svalue += ':'+posslti;
+                    }
+                }
+                break;
+            }
+        }
+    }
+    assemble();
+}
+
+function toggleDeepLink() {
+    var sform=choices.document.forms.sch;
+    if (sform.deeplinktypes.length) {
+        var frame = window.frames["choices"];
+        for (var i=0; i<sform.deeplinktypes.length; i++) {
+            if (sform.deeplinktypes[i].checked) {
+                if (sform.deeplinktypes[i].value == 'key') {
+                    if (frame.document.getElementById('deeplinkkey')) {
+                        frame.document.getElementById('deeplinkkey').type='text';
+                    }
+                    if (frame.document.getElementById('deeplinkltidiv')) {
+                        frame.document.getElementById('deeplinkltidiv').style.display='none';
+                    }
+                } else {
+                    if (frame.document.getElementById('deeplinkkey')) {
+                        frame.document.getElementById('deeplinkkey').type='hidden';
+                    }
+                    if (frame.document.getElementById('deeplinkltidiv')) {
+                        if (sform.deeplinktypes[i].value == 'lti') {
+                            frame.document.getElementById('deeplinkltidiv').style.display='inline-block';
+                        } else {
+                            frame.document.getElementById('deeplinkltidiv').style.display='none';
+                        }
+                    }
+                }
+                break;
+            }
+        }
+    }
+}
+
+function calldeeplink() {
+    return 'onclick="parent.toggleDeepLink()"';
+}
+
 function integereval() {
    svalue=choices.document.forms.sch.intval.value;
    svalue=Math.round(svalue);
@@ -575,8 +639,7 @@
    if (color==svalue) { selection="<font color='#"+col[10-ir]+col[10-ig]+col[10-ib]+"'>X</font>"; }
    choicewrite('<td bgcolor="'+color+'"><a href="javascript:parent.pickcolor('+"'"+
                color+"'"+')">'+selection+'</a></td>');
-               
-}    
+}
 
 function draw() {
    choicestart();
@@ -1058,32 +1121,124 @@
            if (svalue=='map_map') { choicewrite(' checked="checked"'); }
            choicewrite(' /> Yes, and the scope of student selected slot is the enclosing map/folder. When checking in, all resources in the map/folder are checked in.</label><br />');
            choicewrite('</td></tr></table>');
-      }
-      if (pscat=='deeplink') {
+       }
+       if (pscat=='deeplink') {
+           var deeplinkvals = new Array();
+           var linktypeparts = new Array();
+           var ltikeyRegExp = /^(lti|key):(\w+)$/;
+           var dlinkkeysty = 'hidden';
+           var dlinkltidivsty = 'none';
+           var dlinkkeyval = '';
+           if ((svalue != '') && (svalue != null)) {
+               deeplinkvals = svalue.split(',');
+               if (ltikeyRegExp.test(deeplinkvals[2])) {
+                   linktypeparts = deeplinkvals[2].split(':');
+                   deeplinkvals[2] = linktypeparts[0];
+                   if (linktypeparts[0] == 'key') {
+                       dlinkkeysty = 'text';
+                       dlinkkeyval = linktypeparts[1];
+                   } else if (linktypeparts[0] == 'lti') {
+                       dlinkltidivsty = 'inline-block';
+                   }
+               }
+           } else {
+               deeplinkvals = ['full','res','any'];
+           }
+           var deeplinklisting = new Array();
+           deeplinklisting = ['full','absent','grades','details','datestatus'];
+           var deeplinklisttxt = new Array();
+           deeplinklisttxt = ['Listed (linked) in both','Not listed','Listed in grades only','Listed (unlinked) in both','Listed (unlinked) inc. status in both'];
+           var deeplinkscopes = new Array();
+           deeplinkscopes = ['res','map','rec'];
+           var deeplinkscopetxt = new Array();
+           deeplinkscopetxt = ['resource only','enclosing map/folder','recursive map/folder'];
+           var deeplinkurls = new Array();
+           deeplinkurls = ['any','only','key','lti'];
            tablestart('Deep-linked items');
-           choicewrite('<tr><td>Value:</td><td colspan="2">');
-           choicewrite('<label><input name="stringval" value="full"'+
-                  ' type="radio" '+callradiostringeval('full'));
-           if (svalue=='full') { choicewrite(' checked="checked"'); }
-           choicewrite(' /> Displayed (linked) in Contents and Grades.</label><br />');
-           choicewrite('<label><input name="stringval" value="absent"'+
-                  ' type="radio" '+callradiostringeval('absent'));
-           if (svalue=='absent') { choicewrite(' checked="checked"'); }
-           choicewrite(' /> Not displayed in Contents or Grades.</label><br />');
-           choicewrite('<label><input name="stringval" value="grades"'+
-                  ' type="radio" '+callradiostringeval('grades'));
-           if (svalue=='grades') { choicewrite(' checked="checked"'); }
-           choicewrite(' /> Displayed in Grades only.</label><br />');
-           choicewrite('<label><input name="stringval" value="details"'+
-                  ' type="radio" '+callradiostringeval('details'));
-           if (svalue=='details') { choicewrite(' checked="checked"'); }
-           choicewrite(' /> Displayed (unlinked) in Contents and Grades.</label><br />');
-           choicewrite('<label><input name="stringval" value="datestatus"'+
-                  ' type="radio" '+callradiostringeval('datestatus'));
-           if (svalue=='datestatus') { choicewrite(' checked="checked"'); }
-           choicewrite(' /> Displayed (with date status) but unlinked in Contents and Grades.</label><br />');
+           choicewrite('<tr><td>In Contents or Gradebook?</td><td>');
+           choicewrite('<select name="deeplinklisted">');
+           for (var i=0; i<deeplinklisting.length; i++) {
+               choicewrite('<option value="'+deeplinklisting[i]+'"');
+               if (deeplinkvals[0] == deeplinklisting[i]) {
+                   choicewrite(' selected="selected"');
+               }
+               choicewrite('>'+deeplinklisttxt[i]+'</option>');
+           }
+           choicewrite('</select></td></tr>');
+           choicewrite('<tr><td>Access scope via deep-link</td><td>');
+           choicewrite('<select name="deeplinkacc">');
+           for (var i=0; i<deeplinkscopes.length; i++) {
+               choicewrite('<option value="'+deeplinkscopes[i]+'"');
+               if (deeplinkvals[1] == deeplinkscopes[i]) {
+                   choicewrite(' selected="selected"');
+               }
+               choicewrite('>'+deeplinkscopetxt[i]+'</option>');
+           }
+           choicewrite('</select></td></tr>');
+           choicewrite('<tr><td>Supported Link Types</td><td>');
+           choicewrite('<span style="white-space: nowrap;"><label>');
+           choicewrite('<input name="deeplinktypes" value="any"'+
+                  ' type="radio" '+calldeeplink());
+           if (deeplinkvals[2]=='any') { choicewrite(' checked="checked"'); }
+           choicewrite(' /> regular + deep</label></span><br />');
+           choicewrite('<span style="white-space: nowrap;"><label>');
+           choicewrite('<input name="deeplinktypes" value="only"'+
+                  ' type="radio" '+calldeeplink());
+           if (deeplinkvals[2]=='only') { choicewrite(' checked="checked"'); }
+           choicewrite(' /> deep only</label></span><br />');
+           choicewrite('<span style="white-space: nowrap;"><label>');
+           choicewrite('<input name="deeplinktypes" value="key"'+
+                  ' type="radio" '+calldeeplink());
+           if (deeplinkvals[2]=='key') { choicewrite(' checked="checked"'); }
+           choicewrite(' /> deep with key</label>');
+           choicewrite('<input type="'+dlinkkeysty+'" name="deeplinkkey" id="deeplinkkey" value="'+dlinkkeyval+'" size="6" />');
+           choicewrite('</span><br />');
+           if ((pextra != '') && (pextra != null)) {
+               var ltiRegExp = /^lti_/;
+               if (ltiRegExp.test(pextra)) {
+                   pextra = pextra.replace(ltiRegExp,'');
+                   var posslti = pextra.split(',');
+                   if (posslti.length >= 1) {
+                       var ltinums = new Array();
+                       var ltititles = new Array();
+                       for (var i=0; i<posslti.length; i++) {
+                           var entries = posslti[i].split(':');
+                           ltinums[i] = entries[0];
+                           ltititles[i] = decodeURI(entries[1]);
+                       }
+                       if (ltinums.length) {
+                           choicewrite('<span style="white-space: nowrap;"><label>');
+                           choicewrite('<input name="deeplinktypes" value="lti"'+
+                                       ' type="radio" '+calldeeplink());
+                           if (deeplinkvals[2]=='lti') { choicewrite(' checked="checked"'); }
+                           choicewrite(' /> deep with LTI launch</label>');
+                           choicewrite('<div id="deeplinkltidiv" style="display:'+dlinkltidivsty+'">');
+                           choicewrite('<select name="linkposslti">');
+                           var sel='';
+                           if (deeplinkvals[2]!='lti') {
+                               sel = ' selected="selected"';
+                           }
+                           if (ltinums.length > 1) {
+                               choicewrite('<option value=""'+sel+'>Please select</option>');
+                           }
+                           for (var i=0; i<ltinums.length; i++) {
+                               sel = '';
+                               if (deeplinkvals[2]=='lti') {
+                                   if (linktypeparts.length) {
+                                       if (ltinums[i] == linktypeparts[1]) {
+                                           sel = ' selected="selected"';
+                                       }
+                                   }
+                               }
+                               choicewrite('<option value="'+ltinums[i]+'"'+sel+'>'+ltititles[i]+'</option>');
+                           }
+                           choicewrite('</select></div></span><br />');
+                       }
+                   }
+               }
+           }
            choicewrite('</td></tr></table>');
-      }
+       }
    }
 
    if (ptype=='color') {
@@ -1221,6 +1376,7 @@
      }
      if (pair[0]=='defmin' && pair[1] >= 0 && pair[1] < 60) { defmin=pair[1]; }
      if (pair[0]=='defsec' && pair[1] >= 0 && pair[1] < 60) { defsec=pair[1]; }
+     if (pair[0]=='extra') { pextra=pair[1]; }
   }
 
   var tablecol = '';
@@ -1411,7 +1567,7 @@
      else if (pscat == 'useslots')     { sopt('useslots','Slots control access'); }
      else if (pscat == 'deeplink')     { sopt('deeplink','Deep-linked items'); }
      else { pscat = 'any'; }
-     sopt('any','String Value');
+     if (pscat != 'deeplink') { sopt('any','String Value'); }
   }
 
   if (ptype=='color') {
@@ -1442,6 +1598,8 @@
   }
   if ((ptype=='date') && (pscat=='interval')) {
       selwrite('<a href="javascript:parent.validateInterval();');
+  } else if ((ptype=='string') && (pscat=='deeplink')) {
+      selwrite('<a href="javascript:parent.validateDeepLink();');
   } else {
       selwrite('<a href="javascript:parent.assemble();');
   }


More information about the LON-CAPA-cvs mailing list