--- loncom/interface/lonextresedit.pm 2023/05/22 21:10:55 1.31 +++ loncom/interface/lonextresedit.pm 2025/06/14 02:50:25 1.37 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: lonextresedit.pm,v 1.31 2023/05/22 21:10:55 raeburn Exp $ +# $Id: lonextresedit.pm,v 1.37 2025/06/14 02:50:25 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -109,7 +109,7 @@ sub handler { %ltitools = ( dom => \%domtools, crs => \%crstools, - ); + ); } my $js = &Apache::lonhtmlcommon::scripttag(&extedit_javascript()); my $pathitem = ''; } else { my $class = 'LC_nobreak'; + my ($nocrsdest,$fixeddest,$fixeddelay,$showprovider,$provider,$scheme); if ($residx) { $class = 'LC_docs_ext_edit LC_nobreak'; if ($orig_url =~ m{^/adm/$cdom/$cnum/(\d+)/ext\.tool$}) { @@ -508,19 +560,14 @@ sub extedit_form { if ($toolhash{'id'} =~/^c(\d+)$/) { $tool = $1; $tooltype = 'crs'; - if (ref($ltitools) eq 'HASH') { - if (ref($ltitools->{'crs'}) eq 'HASH') { - $ltihash = $ltitools->{'crs'}->{$tool}; - } - } } elsif ($toolhash{'id'} =~/^\d+$/) { $tooltype = 'dom'; $tool = $toolhash{'id'}; - if (ref($ltitools) eq 'HASH') { - if (ref($ltitools->{'dom'}) eq 'HASH') { - $ltihash = $ltitools->{'dom'}->{$tool}; - } - } + } + if (($tool ne '') && ($tooltype ne '') && (ref($ltitools) eq 'HASH')) { + if (ref($ltitools->{$tooltype}) eq 'HASH') { + $ltihash = $ltitools->{$tooltype}->{$tool}; + } } if (($tool ne '') && (ref($ltihash) eq 'HASH')) { my $tooltitle = $ltihash->{'title'}; @@ -529,10 +576,10 @@ sub extedit_form { if ($icon) { $image = ''.$tooltitle.''; } - if ($ltihash->{'url'} =~ m{://}) { - (my $prot,my $host,$providerurl) = ($ltihash->{'url'} =~ m{^([^/]+)://([^/]+)(|/.+)$}); + if ($ltihash->{'url'} =~ m{^https?\://}) { + ($scheme,$provider,$path) = ($ltihash->{'url'} =~ m{^(https?\://)([^/]+)(|/.+)$}); } else { - $providerurl = $ltihash->{'url'}; + $path = $ltihash->{'url'}; } $tooltarget = $toolhash{'target'}; if ($tooltarget eq 'window') { @@ -566,6 +613,7 @@ sub extedit_form { if ($ltihash->{'crsconf'}->{'append'}) { $crsappend = $toolhash{'crsappend'}; $appendstyle = 'display:inline'; + $showprovider = 1; } if ($ltihash->{'crsconf'}->{'target'}) { $dispdivstyle = 'display:block'; @@ -576,9 +624,52 @@ sub extedit_form { 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'; + } + } + if ($ltihash->{'crsconf'}->{'desturl'}) { + $desturl = $toolhash{'desturl'}; + $desturlstyle = 'display:inline'; + $delay = $toolhash{'delay'}; + $showprovider = 1; + if ($desturl ne '') { + $desturlinfostyle = 'display:inline'; + $chkdest = ' checked="checked"'; + $chknodest = ''; + } else { + $desturlinfostyle = 'display:none'; + $chkdest = ''; + $chknodest = ' checked="checked"'; + } + } else { + $nocrsdest = 1; + } } $toolelem = ''.$image.' '.$tooltitle.'
'; $gradablestyle = 'display:inline'; + if (($ltihash->{'desturl'}) && ($nocrsdest) && ($ltihash->{'defdest'} =~ m{^(https?\://|/)})) { + $fixeddest = $ltihash->{'defdest'}; + if ($ltihash->{'defdelay'} =~ /^\d+\.?\d*$/) { + $fixeddelay = $ltihash->{'defdelay'}; + } + $desturlfixedstyle = 'display:inline-block'; + $showprovider = 1; + } + if (($showprovider) && ($provider ne '')) { + $providerstyle = 'display:inline-block'; + } } } } else { @@ -631,7 +722,7 @@ sub extedit_form { $exttypeofftext = &mt('No external tools defined in the domain are available for selection.'); } elsif (!$numcrstools && $numdomtools) { $defcheck{'dom'} = ' checked="checked"'; - $subdivstyle = 'display:none'; + $subdivstyle = 'display:block'; $exttypeonsty = 'display:block'; my $firstoption = ''; $seloptions = &ordered_tooloptions($ltitools->{'dom'}); @@ -658,9 +749,49 @@ sub extedit_form { $crslabel = $env{'course.'.$cdom.'_'.$cnum.'.internal.coursecode'}; $crstitle = $env{'course.'.$cdom.'_'.$cnum.'.description'}; $crsappend = ''; + $returnurl = ''; + $backtourl = ''; + $customreturn = 'hidden'; $chknogrd = ' checked="checked"'; - } - $toolelem .= '
'. + $chknoreturn = ''; + $chkreturndef = ' checked="checked"'; + $chkreturncust = ''; + $chknodest = ' checked="checked"'; + $chkdest = ''; + } + my $onclickreturl = ' onclick="updateReturnUrl('."this.form,'$toolattr{'customreturnurl'}','$toolattr{'returnurldiv'}','exttoolreturnurl'".');"'; + my $onclickdest = ' onclick="updateDestUrl('."this.form,'$toolattr{'desturlinfodiv'}','$toolattr{'desturldiv'}','exttooldest'".');"'; + $toolelem.= '
'. + ''.&mt('Provider').': '.$scheme.$provider.'
'. + ''.&mt('Provider path').': '.$path.''."\n". + '
'."\n". + '
'. + '
'. + ''.&mt('Append to LTI login URL').':
'. + ''. + '
'."\n". + '
'. + '
'. + ''.&mt('Post-login destination different from path').': '. + ''.(' 'x2). + ''.(' 'x2). + '
'."\n". + '
'. + ''. + '
'. + '
'."\n". + '
'. + ''.&mt('Destination after provider login').': '. + '
'.$fixeddest.'
'. + '
'. + &mt('Post-login delay before redirect to destination').': '.$fixeddelay.' s'."\n". + '
'. + '
'. + '
'. ''.&mt('Display target:').' '. '
'; - $toolelem .= '
'. - '
'. - ''.&mt('Link Text').'
'. - '
'. - ''.&mt('Explanation').'
'. - '
'. - '
'; - $toolelem .= '
'. + '
'. + '
'. + '
'. + ''.&mt('Link Text').'
'. + '
'. + ''.&mt('Explanation').'
'. + '
'. + '
'. + '
'. ''.&mt('Course label:').' '. '
'. - '
'. + ''."\n". '
'. ''.&mt('Course title:').' '. '
'. - '
'. - '
'. - ''.&mt('Append to URL[_1]', - ' ('.$providerurl.')
'). - '

'. - '
'. + ''."\n". '
'. ''.&mt('Gradable').' '. ''.(' 'x2). '
'; + ' />'.&mt('No').'
'."\n". + '
'. + ''.&mt('Include return URL').': '. + ''.(' 'x2). + ''.(' 'x2). + '
'."\n". + ''. + '
'."\n"; } my $chooser = $toolelem; if ($type eq 'ext') { $chooser = "
+ $preview
"; } + my $idattr; + unless ($subdivid eq '') { + $idattr = 'id="'.$subdivid.'"'; + } $form = <
$legend $active $chooser -
+
+ $pathitem $hiddenelem @@ -823,7 +967,8 @@ sub extedit_javascript { my ($toolsjs,$exttoolnums,$exttooloptions); if (ref($toolsref) eq 'HASH') { $toolsjs = " var ltitools = new Array();\n". - " var ltitoolsUrl = new Array();\n". + " var ltitoolsProvider = new Array();\n". + " var ltitoolsPath = new Array();\n". " var ltitoolsTarget = new Array();\n". " var ltitoolsWidth = new Array();\n". " var ltitoolsHeight = new Array();\n". @@ -834,7 +979,11 @@ sub extedit_javascript { " 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". + " var ltitoolsDestUrl = new Array();\n". + " var ltitoolsDefDest = new Array();\n". + " var ltitoolsDefDelay = new Array();\n"; $exttoolnums = " var ltitoolsnum = new Array();\n". " var tooloptval = new Array();\n". " var toolopttxt = new Array();\n"; @@ -843,7 +992,8 @@ sub extedit_javascript { if (ref($toolsref->{$type}) eq 'HASH') { my $num = scalar(keys(%{$toolsref->{$type}})); $toolsjs .= " ltitools[$idx] = new Array($num);\n". - " ltitoolsUrl[$idx] = new Array($num);\n". + " ltitoolsProvider[$idx] = new Array($num);\n". + " ltitoolsPath[$idx] = new Array($num);\n". " ltitoolsTarget[$idx] = new Array($num);\n". " ltitoolsWidth[$idx] = new Array($num);\n". " ltitoolsHeight[$idx] = new Array($num);\n". @@ -854,7 +1004,11 @@ sub extedit_javascript { " 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". + " ltitoolsDestUrl[$idx] = new Array($num);\n". + " ltitoolsDefDest[$idx] = new Array($num);\n". + " ltitoolsDefDelay[$idx] = new Array($num);\n"; my $i=0; foreach my $key (sort { $a <=> $b } keys(%{$toolsref->{$type}})) { if (ref($toolsref->{$type}->{$key}) eq 'HASH') { @@ -864,21 +1018,24 @@ sub extedit_javascript { my $height = $toolsref->{$type}->{$key}->{'display'}->{'height'}; my $linkdef = $toolsref->{$type}->{$key}->{'display'}->{'linktext'}; my $explaindef = $toolsref->{$type}->{$key}->{'display'}->{'explanation'}; - my $providerurl; - if ($toolsref->{$type}->{$key}->{'url'} =~ m{://}) { - (my $prot,my $host,$providerurl) = - ($toolsref->{$type}->{$key}->{'url'} =~ m{^([^/]+)://([^/]+)(|/.+)$}); + my ($scheme,$provider,$path); + if ($toolsref->{$type}->{$key}->{'url'} =~ m{^https?\://}) { + ($scheme,$provider,$path) = + ($toolsref->{$type}->{$key}->{'url'} =~ m{^(https?\://)([^/]+)(|/.+)$}); } else { - $providerurl = $toolsref->{$type}->{$key}->{'url'}; + $path = $toolsref->{$type}->{$key}->{'url'}; } - $providerurl = &LONCAPA::map::qtunescape($providerurl); + $scheme = &LONCAPA::map::qtunescape($scheme); + $provider = &LONCAPA::map::qtunescape($provider); + $path = &LONCAPA::map::qtunescape($path); $toolsjs .= " ltitools[$idx][$i] = '$key';\n". " ltitoolsTarget[$idx][$i] = '$target';\n". " ltitoolsWidth[$idx][$i] = '$width';\n". " ltitoolsHeight[$idx][$i] = '$height';\n". " ltitoolsLinkDef[$idx][$i] = '$linkdef';\n". " ltitoolsExplainDef[$idx][$i] = '$explaindef';\n". - " ltitoolsUrl[$idx][$i] = '$providerurl';\n"; + " ltitoolsProvider[$idx][$i] = '$scheme$provider';\n". + " ltitoolsPath[$idx][$i] = '$path';\n"; } if (ref($toolsref->{$type}->{$key}->{'crsconf'}) eq 'HASH') { my $display = $toolsref->{$type}->{$key}->{'crsconf'}->{'target'}; @@ -893,7 +1050,15 @@ sub extedit_javascript { $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"; + my $desturl = $toolsref->{$type}->{$key}->{'crsconf'}->{'desturl'}; + $toolsjs .= " ltitoolsDestUrl[$idx][$i] = '$desturl';\n"; + } + my $defdest = $toolsref->{$type}->{$key}->{'defdest'}; + $toolsjs .= " ltitoolsDefDest[$idx][$i] = '$defdest';\n"; + my $defdelay = $toolsref->{$type}->{$key}->{'defdelay'}; + $toolsjs .= " ltitoolsDefDelay[$idx][$i] = '$defdelay';\n"; } $i++; } @@ -1050,10 +1215,12 @@ function setExternal(extform,residx,type 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; + appendinput += '_'+residx; + customreturnurl += '_'+residx; } if (document.getElementById(labelinput)) { var crslabel = document.getElementById(labelinput).value; @@ -1102,6 +1269,59 @@ function setExternal(extform,residx,type } 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 0) { + desturldiv += '_'+residx; + } + if (document.getElementById(desturldiv)) { + if (document.getElementById(desturldiv).style.display == 'inline') { + if (extform.exttooldest.length) { + for (var i=0; i 0) { eval("extform.importdetail.value=title+'='+info+'='+residx;extform.submit();"); @@ -1284,7 +1504,14 @@ function updateExttool(caller,form,suppl titlediv = prefix+'toolcrstitlediv'; appenddiv = prefix+'toolcrsappenddiv'; gradablediv = prefix+'toolgradablediv'; - providerurl = prefix+'toolproviderurl'; + returnurldiv = prefix+'toolreturnurldiv'; + provider = prefix+'toolprovider'; + providerpath = prefix+'toolproviderpath'; + providerdiv = prefix+'toolproviderdiv'; + desturldiv = prefix+'tooldesturldiv'; + desturlfixeddiv = prefix+'tooldesturlfixeddiv'; + fixeddest = prefix+'toolfixeddest'; + fixeddelay = prefix+'toolfixeddelay'; labelinput = prefix+'toolcrslabel'; titleinput = prefix+'toolcrstitle'; appendinput = prefix+'toolcrsappend'; @@ -1297,6 +1524,21 @@ function updateExttool(caller,form,suppl var toolpick = caller.options[caller.selectedIndex].value; $toolsjs if (toolpick == '') { + if (document.getElementById(providerdiv)) { + document.getElementById(providerdiv).style.display = 'none'; + } + if (document.getElementById(desturldiv)) { + document.getElementById(desturldiv).style.display = 'none'; + } + if (document.getElementById(desturlfixeddiv)) { + document.getElementById(desturlfixeddiv).style.display = 'none'; + } + if (document.getElementById(fixeddest)) { + document.getElementById(fixeddest).innerHTML = ''; + } + if (document.getElementById(fixeddelay)) { + document.getElementById(fixeddelay).innerHTML = ''; + } if (document.getElementById(dispdiv)) { document.getElementById(dispdiv).style.display = 'none'; } @@ -1324,6 +1566,9 @@ function updateExttool(caller,form,suppl 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']; @@ -1342,6 +1587,56 @@ function updateExttool(caller,form,suppl if (ltitools[i].length > 0) { for (var j=0; j'; - } - } - } else { - document.getElementById(appenddiv).style.display = 'none'; - if (document.getElementById(providerurl)) { - document.getElementById(providerurl).innerHTML = ''; - } - } - } if (document.getElementById(gradablediv)) { if (supplementalflag != 1) { 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; } } @@ -1450,6 +1737,30 @@ function updateExttool(caller,form,suppl } } +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