[LON-CAPA-cvs] cvs: loncom /interface courseprefs.pm lonconfigsettings.pm londocs.pm lonextresedit.pm lonexttool.pm
raeburn
raeburn at source.lon-capa.org
Fri Mar 14 21:03:33 EDT 2025
raeburn Sat Mar 15 01:03:33 2025 EDT
Modified files:
/loncom/interface courseprefs.pm lonconfigsettings.pm londocs.pm
lonextresedit.pm lonexttool.pm
Log:
- Bug 6754. LON-CAPA as LTI Consumer.
External Tool definition can include: "Return URL sent on launch", and
if Y, value sent can be set in each tool instance in a course.
-------------- next part --------------
Index: loncom/interface/courseprefs.pm
diff -u loncom/interface/courseprefs.pm:1.133 loncom/interface/courseprefs.pm:1.134
--- loncom/interface/courseprefs.pm:1.133 Tue Jan 7 16:19:19 2025
+++ loncom/interface/courseprefs.pm Sat Mar 15 01:03:33 2025
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set configuration settings for a course
#
-# $Id: courseprefs.pm,v 1.133 2025/01/07 16:19:19 raeburn Exp $
+# $Id: courseprefs.pm,v 1.134 2025/03/15 01:03:33 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -2026,10 +2026,14 @@
} else {
$ltitools{$newid}{'display'}{'target'} = 'iframe';
}
- foreach my $item ('passback','roster') {
+ foreach my $item ('passback','roster','returnurl') {
if ($env{'form.ltitools_'.$item.'_add'}) {
$ltitools{$newid}{$item} = 1;
- if ($env{'form.ltitools_'.$item.'valid_add'} ne '') {
+ if ($item eq 'returnurl') {
+ if ($env{'form.ltitools_crs'.$item.'_add'}) {
+ $ltitools{$newid}{'crsconf'}{$item} = 1;
+ }
+ } elsif ($env{'form.ltitools_'.$item.'valid_add'} ne '') {
my $lifetime = $env{'form.ltitools_'.$item.'valid_add'};
$lifetime =~ s/^\s+|\s+$//g;
if ($lifetime =~ /^\d+\.?\d*$/) {
@@ -2213,10 +2217,21 @@
} else {
$haschanges{$itemid} = 1;
}
- foreach my $extra ('passback','roster') {
+ foreach my $extra ('passback','roster','returnurl') {
if ($env{'form.ltitools_'.$extra.'_'.$i}) {
$ltitools{$itemid}{$extra} = 1;
- if ($env{'form.ltitools_'.$extra.'valid_'.$i} ne '') {
+ if ($extra eq 'returnurl') {
+ if ($env{'form.ltitools_crs'.$extra.'_'.$i}) {
+ $ltitools{$itemid}{'crsconf'}{$extra} = 1;
+ if (ref($values->{$itemid}{'crsconf'}) eq 'HASH') {
+ if (!$values->{$itemid}{'crsconf'}{$extra}) {
+ $haschanges{$itemid} = 1;
+ }
+ } else {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ } elsif ($env{'form.ltitools_'.$extra.'valid_'.$i} ne '') {
my $lifetime = $env{'form.ltitools_'.$extra.'valid_'.$i};
$lifetime =~ s/^\s+|\s+$//g;
if ($lifetime =~ /^\d+\.?\d*$/) {
@@ -3341,11 +3356,21 @@
$output .= ' '.&mt('None');
}
$output .= '</li>';
- foreach my $item ('passback','roster') {
+ foreach my $item ('passback','roster','returnurl') {
$output .= '<li>'.$lt{$item}.' ';
if ($changes->{$itemid}{$item}) {
$output .= &mt('Yes');
- if ($changes->{$itemid}{$item.'valid'}) {
+ if ($item eq 'returnurl') {
+ if (ref($changes->{$itemid}{'crsconf'}) eq 'HASH') {
+ $output .= ' ['.&mt('Configurable in course').': ';
+ if ($changes->{$itemid}{'crsconf'}{$item}) {
+ $output .= &mt('Yes');
+ } else {
+ $output .= &mt('No');
+ }
+ $output .= ']';
+ }
+ } elsif ($changes->{$itemid}{$item.'valid'}) {
if ($item eq 'passback') {
$output .= ' '.&mt('valid for at least [quant,_1,day] after launch',
$changes->{$itemid}{$item.'valid'});
@@ -6627,22 +6652,35 @@
'<div class="LC_left_float">'.$lt{'linktext'}.'<br />'.
'<input type="text" name="ltitools_linktext_'.$i.'" size="25" value="'.$currdisp{'linktext'}.'" /></div>'.
'<div class="LC_left_float">'.$lt{'explanation'}.'<br />'.
- '<textarea name="ltitools_explanation_'.$i.'" rows="5" cols="40">'.$currdisp{'explanation'}.
+ '<textarea name="ltitools_explanation_'.$i.'" rows="5" cols="30">'.$currdisp{'explanation'}.
'</textarea></div><div style=""></div><br />';
my %units = (
'passback' => 'days',
'roster' => 'seconds',
);
- foreach my $extra ('passback','roster') {
+ my %courseconfig;
+ if (ref($settings->{$item}) eq 'HASH') {
+ if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') {
+ %courseconfig = %{$settings->{$item}->{'crsconf'}};
+ }
+ }
+ foreach my $extra ('passback','roster','returnurl') {
my $validsty = 'none';
my $currvalid;
my $checkedon = '';
my $checkedoff = ' checked="checked"';
+ my $crscheckedon = '';
+ my $crscheckedoff = ' checked="checked"';
if ($settings->{$item}->{$extra}) {
$checkedon = $checkedoff;
$checkedoff = '';
$validsty = 'inline-block';
- if ($settings->{$item}->{$extra.'valid'} =~ /^\d+\.?\d*$/) {
+ if ($extra eq 'returnurl') {
+ if ($courseconfig{$extra}) {
+ $crscheckedon = ' checked="checked"';
+ $crscheckedoff = '';
+ }
+ } elsif ($settings->{$item}->{$extra.'valid'} =~ /^\d+\.?\d*$/) {
$currvalid = $settings->{$item}->{$extra.'valid'};
}
}
@@ -6651,12 +6689,21 @@
'<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="0"'.$checkedoff.$onclick.' />'.
&mt('No').'</label>'.(' 'x2).
'<label><input type="radio" name="ltitools_'.$extra.'_'.$i.'" value="1"'.$checkedon.$onclick.' />'.
- &mt('Yes').'</label></span></div>'.
- '<div class="LC_floatleft" style="display:'.$validsty.';" id="ltitools_'.$extra.'time_'.$i.'">'.
- '<span class="LC_nobreak">'.
- &mt("until at least [_1] $units{$extra} after launch",
- '<input type="text" name="ltitools_'.$extra.'valid_'.$i.'" value="'.$currvalid.'" />').
- '</span></div><div style="padding:0;clear:both;margin:0;border:0"></div>';
+ &mt('Yes').'</label></span></div>';
+ if ($extra eq 'returnurl') {
+ $datatable .= '<div class="LC_floatleft" style="display:'.$validsty.';" id="ltitools_course'.$extra.'_'.$i.'">'.
+ '<span class="LC_nobreak"> -- '.&mt('configurable in course').': '.
+ '<label><input type="radio" name="ltitools_crs'.$extra.'_'.$i.'" value="0"'.$crscheckedoff.' />'.
+ &mt('No').'</label>'.(' 'x2).
+ '<label><input type="radio" name="ltitools_crs'.$extra.'_'.$i.'" value="1"'.$crscheckedon.' />'.
+ &mt('Yes').'</label>';
+ } else {
+ $datatable .= '<div class="LC_floatleft" style="display:'.$validsty.';" id="ltitools_'.$extra.'time_'.$i.'">'.
+ '<span class="LC_nobreak">'.
+ &mt("until at least [_1] $units{$extra} after launch",
+ '<input type="text" name="ltitools_'.$extra.'valid_'.$i.'" value="'.$currvalid.'" />');
+ }
+ $datatable .= '</span></div><div style="padding:0;clear:both;margin:0;border:0"></div>';
}
$datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.': ';
if ($imgsrc) {
@@ -6742,14 +6789,8 @@
}
$datatable .= '</select></td>';
}
- $datatable .= '</tr></table></fieldset>';
- my %courseconfig;
- if (ref($settings->{$item}) eq 'HASH') {
- if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') {
- %courseconfig = %{$settings->{$item}->{'crsconf'}};
- }
- }
- $datatable .= '<fieldset><legend>';
+ $datatable .= '</tr></table></fieldset>'."\n".
+ '<fieldset><legend>';
if ($context eq 'domain') {
$datatable .= &mt('Configurable in course');
} else {
@@ -6776,14 +6817,14 @@
'<label><input type="checkbox" name="ltitools_customdel_'.$i.'" value="'.
$key.'" />'.&mt('Delete').'</label></span></td><td>'.$key.'</td>'.
'<td><input type="text" name="ltitools_customval_'.$key.'_'.$i.'"'.
- ' value="'.$custom{$key}.'" /></td></tr>';
+ ' value="'.$custom{$key}.'" size="35" /></td></tr>';
}
}
}
$datatable .= '<tr><td><span class="LC_nobreak">'.
'<label><input type="checkbox" name="ltitools_customadd" value="'.$i.'" />'.
&mt('Add').'</label></span></td><td><input type="text" name="ltitools_custom_name_'.$i.'" />'.
- '</td><td><input type="text" name="ltitools_custom_value_'.$i.'" /></td></tr>';
+ '</td><td><input type="text" name="ltitools_custom_value_'.$i.'" size="35" /></td></tr>';
$datatable .= '</table></fieldset></td></tr>'."\n";
$itemcount ++;
}
@@ -6857,18 +6898,27 @@
'passback' => '7',
'roster' => '300',
);
- foreach my $extra ('passback','roster') {
+ foreach my $extra ('passback','roster','returnurl') {
my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','add'".');"';
$datatable .= '<div class="LC_floatleft"><span class="LC_nobreak">'.$lt{$extra}.' '.
'<label><input type="radio" name="ltitools_'.$extra.'_add" value="0" checked="checked"'.$onclick.' />'.
&mt('No').'</label></span>'.(' 'x2).'<span class="LC_nobreak">'.
'<label><input type="radio" name="ltitools_'.$extra.'_add" value="1"'.$onclick.' />'.
- &mt('Yes').'</label></span></div>'.
- '<div class="LC_floatleft" style="display:none;" id="ltitools_'.$extra.'time_add">'.
- '<span class="LC_nobreak">'.
- &mt("until at least [_1] $units{$extra} after launch",
- '<input type="text" name="ltitools_'.$extra.'valid_add" value="'.$defaulttimes{$extra}.'" />').
- '</span></div><div style="padding:0;clear:both;margin:0;border:0"></div>';
+ &mt('Yes').'</label></span></div>';
+ if ($extra eq 'returnurl') {
+ $datatable .= '<div class="LC_floatleft" style="display:none;" id="ltitools_course'.$extra.'_add">'.
+ '<span class="LC_nobreak"> -- '.&mt('configurable in course').': '.
+ '<label><input type="radio" name="ltitools_crs'.$extra.'_add" value="0" checked="checked" />'.
+ &mt('No').'</label>'.(' 'x2).
+ '<label><input type="radio" name="ltitools_crs'.$extra.'_add" value="1" />'.
+ &mt('Yes').'</label>';
+ } else {
+ $datatable .= '<div class="LC_floatleft" style="display:none;" id="ltitools_'.$extra.'time_add">'.
+ '<span class="LC_nobreak">'.
+ &mt("until at least [_1] $units{$extra} after launch",
+ '<input type="text" name="ltitools_'.$extra.'valid_add" value="'.$defaulttimes{$extra}.'" />');
+ }
+ $datatable .= '</span></div><div style="padding:0;clear:both;margin:0;border:0"></div>';
}
$datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.': '.
'('.&mt('if larger than 21x21 pixels, image will be scaled').') ';
@@ -6965,6 +7015,7 @@
'explanation' => 'Default Explanation',
'passback' => 'Tool can return grades:',
'roster' => 'Tool can retrieve roster:',
+ 'returnurl' => 'Return URL sent on launch:',
'crstarget' => 'Display target',
'crslabel' => 'Course label',
'crstitle' => 'Course title',
Index: loncom/interface/lonconfigsettings.pm
diff -u loncom/interface/lonconfigsettings.pm:1.73 loncom/interface/lonconfigsettings.pm:1.74
--- loncom/interface/lonconfigsettings.pm:1.73 Sun Jul 14 16:05:27 2024
+++ loncom/interface/lonconfigsettings.pm Sat Mar 15 01:03:33 2025
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: lonconfigsettings.pm,v 1.73 2024/07/14 16:05:27 raeburn Exp $
+# $Id: lonconfigsettings.pm,v 1.74 2025/03/15 01:03:33 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -269,6 +269,7 @@
if (grep(/^ltitools$/, at actions)) {
$onload .= "toggleLTITools(document.display,'passback','add');".
"toggleLTITools(document.display,'roster','add');".
+ "toggleLTITools(document.display,'returnurl','add');".
"toggleLTITools(document.display,'user','add');";
if (ref($values) eq 'HASH') {
if (ref($values->{'ltitools'}) eq 'HASH') {
@@ -276,6 +277,7 @@
for (my $i=0; $i<$numltitools; $i++) {
$onload .= "toggleLTITools(document.display,'passback','$i');".
"toggleLTITools(document.display,'roster','$i');".
+ "toggleLTITools(document.display,'returnurl','$i');".
"toggleLTITools(document.display,'user','$i');";
}
}
@@ -1118,9 +1120,13 @@
function toggleLTITools(form,setting,item) {
var radioname = '';
var divid = '';
- if ((setting == 'passback') || (setting == 'roster')) {
+ if ((setting == 'passback') || (setting == 'roster') || (setting == 'returnurl')) {
radioname = 'ltitools_'+setting+'_'+item;
- divid = 'ltitools_'+setting+'time_'+item;
+ if (setting == 'returnurl') {
+ divid = 'ltitools_course'+setting+'_'+item;
+ } else {
+ divid = 'ltitools_'+setting+'time_'+item;
+ }
var num = form.elements[radioname].length;
if (num) {
var setvis = '';
Index: loncom/interface/londocs.pm
diff -u loncom/interface/londocs.pm:1.726 loncom/interface/londocs.pm:1.727
--- loncom/interface/londocs.pm:1.726 Fri Feb 28 01:07:59 2025
+++ loncom/interface/londocs.pm Sat Mar 15 01:03:33 2025
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Documents
#
-# $Id: londocs.pm,v 1.726 2025/02/28 01:07:59 raeburn Exp $
+# $Id: londocs.pm,v 1.727 2025/03/15 01:03:33 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1704,7 +1704,7 @@
my $marker = $2;
my $info = $3;
my ($toolid,$toolprefix,$tooltype,%toolhash,%toolsettings);
- my @extras = ('linktext','explanation','crslabel','crstitle','crsappend');
+ my @extras = ('linktext','explanation','crslabel','crstitle','crsappend','returnurl','backtourl');
my @toolinfo = split(/:/,$info);
if ($residx) {
%toolsettings=&Apache::lonnet::dump('exttool_'.$marker,$coursedom,$coursenum);
@@ -1721,7 +1721,8 @@
$toolid =~ s/\D//g;
($toolhash{'target'},$toolhash{'width'},$toolhash{'height'},
$toolhash{'linktext'},$toolhash{'explanation'},$toolhash{'crslabel'},
- $toolhash{'crstitle'},$toolhash{'crsappend'},$toolhash{'gradable'}) = @toolinfo;
+ $toolhash{'crstitle'},$toolhash{'crsappend'},$toolhash{'gradable'},
+ $toolhash{'returnurl'},$toolhash{'backtourl'}) = @toolinfo;
foreach my $item (@extras) {
$toolhash{$item} = &unescape($toolhash{$item});
}
@@ -1808,6 +1809,14 @@
}
}
}
+ if ($tools{'crsconf'}{'returnurl'}) {
+ unless ($toolhash{'returnurl'} eq 'custom') {
+ delete($toolhash{'backtourl'});
+ }
+ } else {
+ delete($toolhash{'returnurl'});
+ delete($toolhash{'backtourl'});
+ }
}
if ($toolhash{'passback'}) {
my $gradesecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
@@ -1836,6 +1845,14 @@
}
}
}
+ if ($residx) {
+ if (($toolsettings{'backtourl'} ne '') && (!exists($toolhash{'backtourl'}))) {
+ push(@deleted,'backtourl');
+ }
+ if (($toolsettings{'returnurl'} ne '') && (!exists($toolhash{'returnurl'}))) {
+ push(@deleted,'returnurl');
+ }
+ }
my $putres = &Apache::lonnet::put('exttool_'.$marker,\%toolhash,$coursedom,$coursenum);
if ($putres eq 'ok') {
if (@deleted) {
Index: loncom/interface/lonextresedit.pm
diff -u loncom/interface/lonextresedit.pm:1.35 loncom/interface/lonextresedit.pm:1.36
--- loncom/interface/lonextresedit.pm:1.35 Mon Feb 3 22:52:36 2025
+++ loncom/interface/lonextresedit.pm Sat Mar 15 01:03:33 2025
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Documents
#
-# $Id: lonextresedit.pm,v 1.35 2025/02/03 22:52:36 raeburn Exp $
+# $Id: lonextresedit.pm,v 1.36 2025/03/15 01:03:33 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -309,12 +309,13 @@
my ($marker,$cdom,$cnum,$supplementalflag,$args) = @_;
my (%newhash,$changed,$newgradable, at deleted,$errormsg);
($newhash{'target'},$newhash{'width'},$newhash{'height'},$newhash{'linktext'},$newhash{'explanation'},
- $newhash{'crslabel'},$newhash{'crstitle'},$newhash{'crsappend'},$newhash{'gradable'}) = split(/:/,$args);
- foreach my $item ('linktext','explanation','crslabel','crstitle','crsappend') {
+ $newhash{'crslabel'},$newhash{'crstitle'},$newhash{'crsappend'},$newhash{'gradable'},
+ $newhash{'returnurl'},$newhash{'backtourl'}) = split(/:/,$args);
+ foreach my $item ('linktext','explanation','crslabel','crstitle','crsappend','backtourl') {
$newhash{$item} = &unescape($newhash{$item});
}
my %toolhash=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum);
- foreach my $item ('target','width','height','linktext','explanation','crslabel','crstitle','crsappend','gradable') {
+ foreach my $item ('target','width','height','linktext','explanation','crslabel','crstitle','crsappend','gradable','returnurl','backtourl') {
$newhash{$item} =~ s/^\s+//;
$newhash{$item} =~ s/\s+$//;
if (($item eq 'width') || ($item eq 'height') || ($item eq 'linktext') || ($item eq 'explanation')) {
@@ -329,6 +330,10 @@
unless ($newhash{$item} == 1) {
$newhash{$item} = '';
}
+ } elsif ($item eq 'backtourl') {
+ unless ($newhash{'returnurl'} eq 'custom') {
+ $newhash{$item} = '';
+ }
}
if ($toolhash{$item} ne $newhash{$item}) {
if (($item eq 'gradable') && (!$supplementalflag)) {
@@ -352,7 +357,7 @@
}
} else {
$toolhash{$item} = $newhash{$item};
- $changed = 1;
+ $changed = 1;
}
}
}
@@ -396,16 +401,17 @@
}
my ($formname,$formid,$toggle,$fieldsetid,$urlid,$subdivid,$dispdivstyle,$dimendivstyle,
$windivstyle,$linktextstyle,$explanationstyle,$labelstyle,$titlestyle,
- $appendstyle,$gradablestyle,$subdivstyle,$legend,$urlelem,$toolelem,%toolattr);
+ $appendstyle,$gradablestyle,$returnurlstyle,$subdivstyle,$legend,$urlelem,
+ $toolelem,%toolattr);
$formname = 'new'.$type;
$toggle = $type;
$fieldsetid = 'external'.$type.'form';
$urlid = $type.'url';
map { $toolattr{$_} = $type.$_; } ('dispdiv','dimendiv','dimenwidth','dimenheight',
'crstitlediv','crslabeldiv','crsappenddiv',
- 'gradablediv','crstitle','crslabel','crsappend',
- 'windiv','linktextdiv','explanationdiv',
- 'linktext','explanation','providerurl');
+ 'gradablediv','returnurldiv','crstitle','crslabel',
+ 'crsappend','windiv','linktextdiv','explanationdiv',
+ 'linktext','explanation','providerurl','customreturnurl');
$dispdivstyle = 'display:none';
$dimendivstyle = 'display:none';
$windivstyle = 'display:none';
@@ -415,6 +421,7 @@
$titlestyle = 'display:none';
$appendstyle = 'display:none';
$gradablestyle = 'display:none';
+ $returnurlstyle = 'display:none';
$subdivstyle = 'display:block';
if ($supplementalflag) {
$formname = 'newsupp'.$type;
@@ -425,7 +432,8 @@
}
my ($link,$legend,$active,$srcclass,$extsrc,$preview,$title,$save,$crstitle,$crslabel,
$crsappend,$fieldsetstyle,$action,$hiddenelem,$form,$width,$height,$tooltarget,
- $linktext,$explanation,$providerurl,$chkgrd,$chknogrd,%chkstate);
+ $linktext,$explanation,$providerurl,$returnurl,$chkgrd,$chknogrd,%chkstate,
+ $chknoreturn,$chkreturndef,$chkreturncust,$customreturn,$backtourl);
$fieldsetstyle = 'display: none;';
$action = '/adm/coursedocs';
my $protocol = ($ENV{'SERVER_PORT'} == 443?'https':'http');
@@ -576,6 +584,21 @@
if ($ltihash->{'crsconf'}->{'explanation'}) {
$explanationstyle = 'padding:0;display:inline';
}
+ if ($ltihash->{'crsconf'}->{'returnurl'}) {
+ $returnurl = $toolhash{'returnurl'};
+ $returnurlstyle = 'display:inline';
+ $backtourl = $toolhash{'backtourl'};
+ if ($returnurl eq 'none') {
+ $chknoreturn = ' checked="checked"';
+ $customreturn = 'hidden';
+ } elsif (($returnurl eq 'custom') && ($backtourl ne '')) {
+ $chkreturncust = ' checked="checked"';
+ $customreturn = 'text';
+ } else {
+ $chkreturndef = ' checked="checked"';
+ $customreturn = 'hidden';
+ }
+ }
}
$toolelem = '<span class="LC_nobreak">'.$image.' '.$tooltitle.'</span><br />';
$gradablestyle = 'display:inline';
@@ -658,8 +681,15 @@
$crslabel = $env{'course.'.$cdom.'_'.$cnum.'.internal.coursecode'};
$crstitle = $env{'course.'.$cdom.'_'.$cnum.'.description'};
$crsappend = '';
+ $returnurl = '';
+ $backtourl = '';
+ $customreturn = 'hidden';
$chknogrd = ' checked="checked"';
+ $chknoreturn = '';
+ $chkreturndef = ' checked="checked"';
+ $chkreturncust = '';
}
+ my $onclickreturl = ' onclick="updateReturnUrl('."this.form,'$toolattr{'customreturnurl'}','$toolattr{'returnurldiv'}','exttoolreturnurl'".');"';
$toolelem .= '<div id="'.$toolattr{'dispdiv'}.'" style="'.$dispdivstyle.'">'.
'<span class="'.$class.'">'.&mt('Display target:').' '.
'<label><input type="radio" name="exttooltarget" value="iframe" '.$chkstate{'iframe'}.'onclick="updateTooldim(this.form,'.
@@ -687,22 +717,32 @@
$toolelem .= '<div id="'.$toolattr{'crslabeldiv'}.'" style="'.$labelstyle.'">'.
'<span class="'.$class.'">'.&mt('Course label:').' '.
'<input type="text" id="'.$toolattr{'crslabel'}.'" name="exttoollabel" value="'.$crslabel.'"'.$disabled.' /></span><br />'.
- '</div>'.
+ '</div>'."\n".
'<div id="'.$toolattr{'crstitlediv'}.'" style="'.$titlestyle.'">'.
'<span class="'.$class.'">'.&mt('Course title:').' '.
'<input type="text" id="'.$toolattr{'crstitle'}.'" name="exttooltitle" value="'.$crstitle.'"'.$disabled.' /></span><br />'.
- '</div>'.
+ '</div>'."\n".
'<div id="'.$toolattr{'crsappenddiv'}.'" style="'.$appendstyle.'">'.
'<span class="'.$class.'">'.&mt('Append to URL[_1]',
'<span id="'.$toolattr{'providerurl'}.'"> ('.$providerurl.')<br /></span>').
'<input type="text" id="'.$toolattr{'crsappend'}.'" size="30" name="exttoolappend" value="'.$crsappend.'"'.$disabled.' /></span><br />'.
- '</div>'.
+ '</div>'."\n".
'<div id="'.$toolattr{'gradablediv'}.'" style="'.$gradablestyle.'">'.
'<span class="'.$class.'">'.&mt('Gradable').' '.
'<label><input type="radio" name="exttoolgradable" value="1"'.$chkgrd.$disabled.
' />'.&mt('Yes').'</label>'.(' 'x2).
'<label><input type="radio" name="exttoolgradable" value="0"'.$chknogrd.$disabled.
- ' />'.&mt('No').'</label></span></div>';
+ ' />'.&mt('No').'</label></span><br /></div>'."\n".
+ '<div id="'.$toolattr{'returnurldiv'}.'" style="'.$returnurlstyle.'">'.
+ '<span class="'.$class.'">'.&mt('Include return URL').': '.
+ '<label><input type="radio" name="exttoolreturnurl" value="none"'.$chknoreturn.$disabled.$onclickreturl.' />'.
+ &mt('No').'</label>'.(' 'x2).
+ '<label><input type="radio" name="exttoolreturnurl" value="default"'.$chkreturndef.$disabled.$onclickreturl.' />'.
+ &mt('Yes, default URL').'</label>'.(' 'x2).
+ '<label><input type="radio" name="exttoolreturnurl" value="custom"'.$chkreturncust.$disabled.$onclickreturl.' />'.
+ &mt('Yes, specify URL').'</label></span><br />'."\n".
+ '<input type="'.$customreturn.'" id="'.$toolattr{'customreturnurl'}.'" size="35" name="exttoolbacktourl" value="'.$backtourl.'"'.$disabled.' />'.
+ '</div>'."\n";
}
my $chooser = $toolelem;
if ($type eq 'ext') {
@@ -842,7 +882,8 @@
" var ltitoolsExplain = new Array();\n".
" var ltitoolsLabel = new Array();\n".
" var ltitoolsTitle = new Array();\n".
- " var ltitoolsAppend = new Array();\n";
+ " var ltitoolsAppend = new Array();\n".
+ " var ltitoolsReturnUrl = new Array();\n";
$exttoolnums = " var ltitoolsnum = new Array();\n".
" var tooloptval = new Array();\n".
" var toolopttxt = new Array();\n";
@@ -862,7 +903,8 @@
" ltitoolsExplain[$idx] = new Array($num);\n".
" ltitoolsLabel[$idx] = new Array($num);\n".
" ltitoolsTitle[$idx] = new Array($num);\n".
- " ltitoolsAppend[$idx] = new Array($num);\n";
+ " ltitoolsAppend[$idx] = new Array($num);\n".
+ " ltitoolsReturnUrl[$idx] = new Array($num);\n";
my $i=0;
foreach my $key (sort { $a <=> $b } keys(%{$toolsref->{$type}})) {
if (ref($toolsref->{$type}->{$key}) eq 'HASH') {
@@ -901,6 +943,8 @@
$toolsjs .= " ltitoolsTitle[$idx][$i] = '$title';\n";
my $append = $toolsref->{$type}->{$key}->{'crsconf'}->{'append'};
$toolsjs .= " ltitoolsAppend[$idx][$i] = '$append';\n";
+ my $returnurl = $toolsref->{$type}->{$key}->{'crsconf'}->{'returnurl'};
+ $toolsjs .= " ltitoolsReturnUrl[$idx][$i] = '$returnurl';\n";
}
}
$i++;
@@ -1058,10 +1102,12 @@
var labelinput = prefix+'toolcrslabel';
var titleinput = prefix+'toolcrstitle';
var appendinput = prefix+'toolcrsappend';
+ var customreturnurl = prefix+'customreturnurl';
if (residx > 0) {
labelinput += '_'+residx;
titleinput += '_'+residx;
appendinput += '_'+residx;
+ customreturnurl += '_'+residx;
}
if (document.getElementById(labelinput)) {
var crslabel = document.getElementById(labelinput).value;
@@ -1110,6 +1156,33 @@
} else {
info += ':';
}
+ var returnurldiv = prefix+'toolreturnurldiv';
+ if (residx > 0) {
+ returnurldiv += '_'+residx;
+ }
+ if (document.getElementById(returnurldiv)) {
+ if (document.getElementById(returnurldiv).style.display == 'inline') {
+ if (extform.exttoolreturnurl.length) {
+ for (var i=0; i<extform.exttoolreturnurl.length; i++) {
+ if (extform.exttoolreturnurl[i].checked) {
+ if (extform.exttoolreturnurl[i].value == 'custom') {
+ var backtourl = extform.exttoolbacktourl.value;
+ backtourl.trim();
+ info += ':custom:'+escape(backtourl);
+ } else if (extform.exttoolreturnurl[i].value == 'default') {
+ info += ':default:';
+ } else {
+ info += ':none:';
+ }
+ }
+ }
+ }
+ } else {
+ info += '::';
+ }
+ } else {
+ info += '::';
+ }
info=escape(info);
if (residx > 0) {
eval("extform.importdetail.value=title+'='+info+'='+residx;extform.submit();");
@@ -1292,6 +1365,7 @@
titlediv = prefix+'toolcrstitlediv';
appenddiv = prefix+'toolcrsappenddiv';
gradablediv = prefix+'toolgradablediv';
+ returnurldiv = prefix+'toolreturnurldiv';
providerurl = prefix+'toolproviderurl';
labelinput = prefix+'toolcrslabel';
titleinput = prefix+'toolcrstitle';
@@ -1332,6 +1406,9 @@
if (document.getElementById(gradablediv)) {
document.getElementById(gradablediv).style.display = 'none';
}
+ if (document.getElementById(returnurldiv)) {
+ document.getElementById(returnurldiv).style.display = 'none';
+ }
} else {
var tooltype = '';
var typeelem = form.elements[prefix+'exttooltype'];
@@ -1449,6 +1526,13 @@
document.getElementById(gradablediv).style.display = 'inline';
}
}
+ if (document.getElementById(returnurldiv)) {
+ if (ltitoolsReturnUrl[i][j]) {
+ document.getElementById(returnurldiv).style.display = 'inline';
+ } else {
+ document.getElementById(returnurldiv).style.display = 'none';
+ }
+ }
break;
}
}
@@ -1458,6 +1542,30 @@
}
}
+function updateReturnUrl(form,typeid,divid,radioname) {
+ if ((document.getElementById(typeid)) &&
+ (document.getElementById(divid))) {
+ if (document.getElementById(divid).style.display == 'inline') {
+ var radelem = form.elements[radioname];
+ var inputtype = 'hidden';
+ if (radelem.length) {
+ for (var i=0; i<radelem.length; i++) {
+ if (radelem[i].checked) {
+ if (radelem[i].value == 'custom') {
+ inputtype = 'text';
+ } else {
+ inputtype = 'hidden';
+ }
+ break;
+ }
+ }
+ }
+ document.getElementById(typeid).type = inputtype;
+ }
+ }
+ return;
+}
+
function updateTooldim(form,dimendiv,windiv,widthinput,heightinput,linkinput,explaininput) {
if (form.exttooltarget.length) {
for (var i=0; i<form.exttooltarget.length; i++) {
Index: loncom/interface/lonexttool.pm
diff -u loncom/interface/lonexttool.pm:1.25 loncom/interface/lonexttool.pm:1.26
--- loncom/interface/lonexttool.pm:1.25 Fri Jun 2 01:20:26 2023
+++ loncom/interface/lonexttool.pm Sat Mar 15 01:03:33 2025
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Launch External Tool Provider (LTI)
#
-# $Id: lonexttool.pm,v 1.25 2023/06/02 01:20:26 raeburn Exp $
+# $Id: lonexttool.pm,v 1.26 2025/03/15 01:03:33 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -120,6 +120,22 @@
foreach my $item (qw(crslabel crstitle crsappend gradable)) {
$toolhash{$item} = $toolsettings{$item};
}
+ if ($toolhash{'returnurl'}) {
+ my $gotreturnurl;
+ if (ref($toolhash{'crsconf'}) eq 'HASH') {
+ if ($toolhash{'crsconf'}{'returnurl'}) {
+ foreach my $item (qw(returnurl backtourl)) {
+ $toolhash{$item} = $toolsettings{$item};
+ }
+ $gotreturnurl = 1;
+ }
+ }
+ unless ($gotreturnurl) {
+ $toolhash{'returnurl'} = 'default';
+ }
+ } else {
+ $toolhash{'returnurl'} = 'none';
+ }
$is_tool = 1;
}
}
@@ -233,7 +249,7 @@
my ($r,$cnum,$cdom,$idx,$submittext,$toolsref) = @_;
my ($version,$context_type,$msgtype,$toolname,$passback,$roster,$locale,
$crslabel,$crstitle,$gradesecret,$rostersecret,%fields,%rolesmap,
- %display,%custom, at userlangs,$incdom);
+ %display,%custom, at userlangs,$incdom,$returnurl,$backtourl);
if (ref($toolsref) eq 'HASH') {
$version = $toolsref->{'version'};
$toolname = $toolsref->{'title'};
@@ -257,6 +273,8 @@
}
$crslabel = $toolsref->{'crslabel'};
$crstitle = $toolsref->{'crstitle'};
+ $returnurl = $toolsref->{'returnurl'};
+ $backtourl = $toolsref->{'backtourl'};
}
if ($version eq '') {
$version = 'LTI-1p0';
@@ -304,11 +322,12 @@
if (scalar(@userlangs) == 1) {
$locale = $userlangs[0];
}
- my ($title,$digest_symb);
+ my ($title,$digest_symb,$digest_suppurl,$resource_link_id);
my ($symb) = &Apache::lonnet::whichuser();
if ($symb) {
$digest_symb = &Encode::decode('UTF-8',$symb);
$digest_symb = &Digest::SHA::sha1_hex($digest_symb);
+ $resource_link_id = $digest_symb;
push(@possdigest,$digest_symb);
my $navmap = Apache::lonnavmaps::navmap->new();
if (ref($navmap)) {
@@ -317,6 +336,10 @@
$title = $res->compTitle();
}
}
+ } elsif ($env{'httpref.'.$env{'request.noversionuri'}} eq '/adm/coursedoc') {
+ $digest_suppurl = &Encode::decode('UTF-8',$env{'request.noversionuri'});
+ $digest_suppurl = &Digest::SHA::sha1_hex($digest_suppurl);
+ $resource_link_id = $digest_suppurl;
}
my $domdesc = &Apache::lonnet::domain($cdom);
my $primary_id = &Apache::lonnet::domain($cdom,'primary');
@@ -327,7 +350,7 @@
lti_version => $version,
lti_message_type => $msgtype,
resource_link_title => $title,
- resource_link_id => $digest_symb,
+ resource_link_id => $resource_link_id,
tool_consumer_instance_guid => $lonhost,
tool_consumer_instance_description => $domdesc,
tool_consumer_info_product_family_code => 'loncapa',
@@ -439,6 +462,51 @@
$ltiparams{$key} = &Encode::decode('UTF-8',$ltiparams{$key});
}
$ltiparams{'basiclti_submit'} = $submittext;
+ if ($returnurl eq 'default') {
+ my $hostname = &Apache::lonnet::hostname($r->dir_config('lonHostID'));
+ my $protocol = 'http';
+ my $port = $r->get_server_port();
+ if ($port eq '443') {
+ $protocol = 'https';
+ }
+ if (&Apache::lonnet::get_proxy_alias()) {
+ my $hdrhost = $r->headers_in->get('Host');
+ if ($hdrhost ne '') {
+ $hostname = $r->headers_in->get('Host');
+ }
+ }
+ my $location = $protocol.'://'.$hostname;
+ if ($display{'target'} eq 'iframe') {
+ my $return_url;
+ if ($symb) {
+ my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
+ my $mapurl = &Apache::lonnet::clutter($map);
+ my $mapsymb = &Apache::lonnet::symbread($map);
+ if ((&Apache::lonnet::EXT('resource.0.encrypturl',$mapsymb) =~ /^yes$/i) &&
+ (!$env{'request.role.adv'})) {
+ $return_url = &Apache::lonenc::encrypted($mapurl);
+ } else {
+ $return_url = $mapurl;
+ }
+ $return_url .= '?navmap=1';
+ } elsif ($env{'httpref.'.$env{'request.noversionuri'}} eq '/adm/coursedoc') {
+ $return_url = '/adm/supplemental';
+ } else {
+ $return_url = '/adm/navmaps';
+ }
+ $ltiparams{'launch_presentation_return_url'} = $location.$return_url;
+ } else {
+ my $uri = $env{'request.noversionuri'};
+ if ($env{'request.enc'}) {
+ $uri = &Apache::lonenc::encrypted($uri);
+ }
+ $ltiparams{'launch_presentation_return_url'} = $location.$uri;
+ }
+ } elsif ($returnurl eq 'custom') {
+ if ($backtourl ne '') {
+ $ltiparams{'launch_presentation_return_url'} = $backtourl;
+ }
+ }
return %ltiparams;
}
More information about the LON-CAPA-cvs
mailing list