--- loncom/interface/lonextresedit.pm 2015/06/09 21:22:56 1.8 +++ loncom/interface/lonextresedit.pm 2016/01/26 14:30:25 1.9 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: lonextresedit.pm,v 1.8 2015/06/09 21:22:56 damieng Exp $ +# $Id: lonextresedit.pm,v 1.9 2016/01/26 14:30:25 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -56,15 +56,19 @@ sub handler { my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $chome = $env{'course.'.$env{'request.course.id'}.'.home'}; - my ($supplementalflag,$updated,$output,$errormsg,$residx,$url,$title,$symb); + my ($supplementalflag,$updated,$output,$errormsg,$residx,$url,$title, + $symb,$type); if (($env{'form.folderpath'} =~ /^supplemental/) && ($env{'form.suppurl'})) { $supplementalflag = 1; + if (&unescape($env{'form.suppurl'}) =~ m{^/adm/$cdom/$cnum/\d+/exttools?$}) { + $type = 'tool'; + } } if (($supplementalflag) || ($env{'form.symb'} =~ /^uploaded/)) { ($updated,$output,$errormsg,$residx,$url,$title,$symb) = &process_changes($supplementalflag,$cdom,$cnum,$chome); if ($supplementalflag) { - if ($url ne $env{'form.suppurl'}) { + if ($url ne &unescape($env{'form.suppurl'})) { $env{'form.suppurl'} = $url; } if ($title ne $env{'form.title'}) { @@ -75,33 +79,48 @@ sub handler { if ($symb ne $env{'form.symb'}) { $env{'form.symb'} = $symb; } + if ($url =~ m{/adm/$cdom/$cnum/\d+/exttools?$}) { + $type = 'tool'; + } } } else { $errormsg = &mt('Information about external resource to edit is missing.'); } if ($updated) { - $output = &Apache::lonhtmlcommon::confirm_success(&mt('External Resource updated')); + my $msg = &mt('External Resource updated'); + if ($type eq 'tool') { + $msg = &mt('External Tool updated'); + } + $output = &Apache::lonhtmlcommon::confirm_success($msg); } if ($errormsg) { $errormsg = '

'.$errormsg.'

'; } + my %ltitools; + if ($type eq 'tool') { + %ltitools = &Apache::lonnet::get_domain_ltitools($cdom); + } my $js = &Apache::lonhtmlcommon::scripttag(&extedit_javascript()); my $pathitem = ''; - $r->print(&Apache::loncommon::start_page('External Resource Editor',$js). + my $description = 'External Resource Editor'; + if ($type eq 'tool') { + $description = 'External Tool Editor'; + } + $r->print(&Apache::loncommon::start_page($description,$js). '
'. $output. $errormsg. &extedit_form($supplementalflag,$residx,$url,$title,$pathitem,undef, - 'direct',$env{'form.symb'}). + 'direct',$env{'form.symb'},$type,$cdom,$cnum,\%ltitools). '
'.&Apache::loncommon::end_page()); return OK; } sub process_changes { my ($supplementalflag,$cdom,$cnum,$chome) = @_; - my ($folder,$container,$output,$errormsg,$updated,$symb,$oldidx,$oldurl, - $oldtitle,$newidx,$newurl,$newtitle,$residx,$url,$title); + my ($folder,$container,$output,$errormsg,$updated,$symb,$oldidx,$oldurl,$type, + $oldtitle,$newidx,$newurl,$newtitle,$residx,$url,$title,$marker,$args); if ($env{'form.symb'}) { $symb = $env{'form.symb'}; (my $map,$oldidx,$oldurl)=&Apache::lonnet::decode_symb($symb); @@ -110,19 +129,27 @@ sub process_changes { $container = $3; } $oldtitle = &Apache::lonnet::gettitle($env{'form.symb'}); + if ($oldurl =~ m{^ext/(.+)$}) { + my $external = $1; + if ($external =~ m{^https://}) { + $oldurl = $external; + } else { + $oldurl = 'http://'.$oldurl; + } + $type = 'ext'; + } else { + $type = 'tool'; + } } elsif ($env{'form.folderpath'}) { $folder = &unescape( (split('&',$env{'form.folderpath'}))[-2] ); $oldurl = &unescape($env{'form.suppurl'}); $oldtitle = &unescape($env{'form.title'}); $container = 'sequence'; $supplementalflag = 1; - } - if ($oldurl =~ m{^ext/(.+)$}) { - my $external = $1; - if ($external =~ m{^https://}) { - $oldurl = $external; + if ($oldurl =~ m{^/adm/$cdom/$cnum/\d+/exttools?$}) { + $type = 'tool'; } else { - $oldurl = 'http://'.$oldurl; + $type = 'ext'; } } $url = $oldurl; @@ -130,6 +157,11 @@ sub process_changes { if ($env{'form.importdetail'}) { ($newtitle,$newurl,$newidx) = map {&unescape($_)} split(/\=/,$env{'form.importdetail'}); + if ($newurl =~ m{^(/adm/$cdom/$cnum/(\d+)/exttools?)\:?(.*)$}) { + $newurl = $1; + $marker = $2; + $args = $3; + } } if ($supplementalflag) { $residx = $newidx; @@ -147,7 +179,18 @@ sub process_changes { if ($mismatchedid) { $errormsg = 'Wrong item identifier'; } elsif (($newtitle eq $oldtitle) && ($newurl eq $oldurl)) { - $output = &mt('No change'); + if ($type eq 'tool') { + if ($args) { + ($updated,$errormsg) = &update_exttool($marker,$cdom,$cnum,$args); + unless ($updated) { + $output = &mt('No change'); + } + } else { + $output = &mt('No change'); + } + } else { + $output = &mt('No change'); + } } else { my $map = "/uploaded/$cdom/$cnum/$folder.$container"; my ($errtext,$fatal) = &LONCAPA::map::mapread($map); @@ -156,8 +199,15 @@ sub process_changes { } else { my $saveurl = &LONCAPA::map::qtunescape($newurl); my $savetitle = &LONCAPA::map::qtunescape($newtitle); + my $ext = 'true'; + if ($type eq 'tool') { + if ($args) { + ($updated,$errormsg) = &update_exttool($marker,$cdom,$cnum,$args); + } + $ext = 'false'; + } $LONCAPA::map::resources[$residx] = - join(':', ($savetitle,$saveurl,'true','normal','res')); + join(':', ($savetitle,$saveurl,$ext,'normal','res')); my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1); if ($errtext) { $errormsg = &mt('Update failed: [_1].',$errtext); @@ -166,8 +216,10 @@ sub process_changes { $title = $newtitle; if ($newurl ne $oldurl) { $url = $newurl; - $newurl =~ s{^http://}{}; - $newurl = "ext/$newurl"; + if ($ext eq 'true') { + $newurl =~ s{^http://}{}; + $newurl = "ext/$newurl"; + } } if (!$supplementalflag) { if ($newurl ne $oldurl) { @@ -195,45 +247,101 @@ sub process_changes { $output = &mt('No change'); } } else { - $errormsg = &mt('Information about current external resource is incomplete.'); + if ($type eq 'tool') { + $errormsg = &mt('Information about current external tool is incomplete.'); + } else { + $errormsg = &mt('Information about current external resource is incomplete.'); + } } return ($updated,$output,$errormsg,$residx,$url,$title,$symb); } +sub update_exttool { + my ($marker,$cdom,$cnum,$args) = @_; + my %toolhash=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum); + my (%newhash,$changed,$errormsg); + ($newhash{'target'},$newhash{'width'},$newhash{'height'}) = split(/:/,$args); + my %toolhash=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum); + foreach my $item ('target','width','height') { + $newhash{$item} =~ s/^\s+//; + $newhash{$item} =~ s/\s+$//; + unless ($item eq 'target') { + if ($newhash{'target'} eq 'iframe') { + $newhash{$item} = ''; + } + } + if ($toolhash{$item} ne $newhash{$item}) { + if ($newhash{$item} eq '') { + delete($toolhash{$item}); + } else { + $toolhash{$item} = $newhash{$item}; + } + $changed = 1; + } + } + if ($changed) { + my $putres = &Apache::lonnet::put('exttool_'.$marker,\%toolhash,$cdom,$cnum); + unless ($putres eq 'ok') { + $errormsg = &mt('Failed to save updated settings.').' '.&mt('Error: [_1].',$putres); + } + } + return ($changed,$errormsg); +} + sub extedit_form { - my ($supplementalflag,$residx,$orig_url,$orig_title,$pathitem,$helpitem,$caller,$symb) = @_; + my ($supplementalflag,$residx,$orig_url,$orig_title,$pathitem,$helpitem,$caller, + $symb,$type,$cdom,$cnum,$ltitools) = @_; + if ($type ne 'tool') { + $type = 'ext'; + } my %lt = &Apache::lonlocal::texthash( ex => 'External Resource', + et => 'External Tool', ed => 'Edit', ee => 'External Resource Editor', + te => 'External Tool Editor', pr => 'Preview', sv => 'Save', ul => 'URL', ti => 'Title', al => 'Add Link', + at => 'Add Tool', ); - my $formname = 'newext'; my $tabid = 'aa'; - my $toggle = 'ext'; - my $fieldsetid = 'uploadextform'; - my $urlid = 'exturl'; my $size = 60; if ($supplementalflag) { - $formname = 'newsuppext'; $tabid = 'ee'; - $toggle = 'suppext'; - $fieldsetid = 'uploadsuppextform'; - $urlid = 'suppexturl'; + } + my ($formname,$formid,$toggle,$fieldsetid,$urlid,$dispdivstyle,$dimendivstyle, + $legend,$urlelem,$toolelem,%toolattr); + $formname = 'new'.$type; + $toggle = $type; + $fieldsetid = 'upload'.$type.'form'; + $urlid = $type.'url'; + map { $toolattr{$_} = $type.$_; } ('dispdiv','dimendiv','dimenwidth','dimenheight'); + $dispdivstyle = 'display:none'; + $dimendivstyle = 'display:none'; + if ($supplementalflag) { + $formname = 'newsupp'.$type; + $toggle = 'supp'.$type; + $fieldsetid = 'uploadsupp'.$type.'form'; + $urlid = 'supp'.$type.'url'; + map { $toolattr{$_} = 'supp'.$toolattr{$_}; } (keys(%toolattr)); } my ($link,$legend,$active,$srcclass,$extsrc,$preview,$title,$save, - $fieldsetstyle,$action,$hiddenelem,$form); + $fieldsetstyle,$action,$hiddenelem,$form,$width,$height,$tooltarget,%chkstate); $fieldsetstyle = 'display: none;'; $action = '/adm/coursedocs'; if ($residx) { if ($caller eq 'direct') { $fieldsetstyle = 'display: block;'; $action = '/adm/extresedit'; - $legend = "$lt{'ee'}"; + if ($type eq 'tool') { + $legend = $lt{'ee'}; + } else { + $legend = $lt{'te'}; + } + $legend = ''.$legend.''; if ($symb) { $hiddenelem = ''; } elsif ($supplementalflag) { @@ -242,50 +350,150 @@ sub extedit_form { ''; } - } else { - $link = ''.$lt{'ed'}.' '."\n"; + } else { + $link = ''.$lt{'ed'}.' '."\n"; $size = 40; $active = ''; } - $formname = "editext_$residx"; - $fieldsetid = "uploadext$residx"; - $urlid = "exturl_$residx"; + $formname = 'edit'.$type.'_'.$residx; + $fieldsetid = 'upload'.$type.$residx; + $urlid = $type.'url_'.$residx; + map { $toolattr{$_} .= '_'.$residx; } (keys(%toolattr)); $srcclass = ' class="LC_nobreak"'; - $extsrc = ''.$lt{'ul'}.' '; - $preview = ' '.$lt{'pr'}.''; + if ($type eq 'ext') { + $extsrc = ''.$lt{'ul'}.' '; + $preview = ' '.$lt{'pr'}.''; + } $title = ''.$lt{'ti'}.' '; $save = $lt{'sv'}; } else { - $link = ''.$lt{'ex'}.''.$helpitem; - $legend = "$lt{'ex'}"; - $extsrc = $lt{'ul'}.':
'; + $link = $lt{'ex'}; + if ($type eq 'tool') { + $link = $lt{'et'}; + } + $link = ''.$link.''.$helpitem; + if ($type eq 'tool') { + $legend = $lt{'te'}; + } else { + $legend = $lt{'ee'}; + } + $legend = ''.$legend.''; $title = $lt{'ti'}.':
'; $residx = 0; - $orig_url = 'http://'; - $orig_title = $lt{'ex'}; - $preview = ''; - $save = $lt{'al'}; + if ($type eq 'ext') { + $orig_url = 'http://'; + $orig_title = $lt{'ex'}; + $extsrc = $lt{'ul'}.':
'; + $preview = ''; + $save = $lt{'al'}; + } else { + $orig_title = $lt{'et'}; + $save = $lt{'at'}; + $orig_url = "/adm/$cdom/$cnum/new/exttool"; + } $pathitem .= '
'; } + $formid = $formname; + if ($type eq 'ext') { + $urlelem = ''; + } else { + my $class = 'LC_nobreak'; + if ($residx) { + $class = 'LC_docs_ext_edit LC_nobreak'; + if ($orig_url =~ m{^/adm/$cdom/$cnum/(\d+)/exttools?$}) { + my $marker = $1; + my %toolhash=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum); + if ($toolhash{'id'}) { + $dispdivstyle = 'display:block'; + if (ref($ltitools) eq 'HASH') { + if (keys(%{$ltitools})) { + if (ref($ltitools->{$toolhash{'id'}}) eq 'HASH') { + my $tooltitle = $ltitools->{$toolhash{'id'}}->{'title'}; + my $icon = $ltitools->{$toolhash{'id'}}->{'image'}; + my $image; + if ($icon) { + $image = ''.$tooltitle.''; + } + $tooltarget = $toolhash{'target'}; + if ($tooltarget eq 'window') { + $dimendivstyle = 'display:block'; + $chkstate{'window'} = 'checked="checked" '; + } else { + $chkstate{'iframe'} = 'checked="checked" '; + } + $width = $toolhash{'width'}; + $height = $toolhash{'height'}; + $toolelem = ''.$image.' '.$tooltitle.'
'; + } + } + } + } + } + } else { + $toolelem = ''."\n". + ''; + } + $toolelem .= '
'. + ''.&mt('Display target:').' '. + ''.(' 'x2). + ''. + '
'. + ''. + &mt('Width').''.(' 'x2). + &mt('Height').''."\n". + '
'; + } + my $chooser = $toolelem; + if ($type eq 'ext') { + $chooser = " +
+ +$extsrc +$urlelem +$preview + +
+"; + } $form = < +
$legend $active - -$extsrc - -$preview - -
+$chooser +
$title $pathitem $hiddenelem - + +
ENDFORM @@ -297,8 +505,8 @@ ENDFORM } sub display_editor { - my ($url,$folderpath,$symb,$idx) = @_; - my ($residx,$supplementalflag,$title,$pathitem,$output); + my ($url,$folderpath,$symb,$idx,$type,$cdom,$cnum) = @_; + my ($residx,$supplementalflag,$title,$pathitem,$output,$js); if ($folderpath =~ /^supplemental/) { $supplementalflag = 1; $residx = $idx; @@ -311,19 +519,51 @@ sub display_editor { my $path = &Apache::loncommon::symb_to_docspath($symb); $pathitem = ''; } - my $js = &Apache::lonhtmlcommon::scripttag(&extedit_javascript()); + my %ltitools; + if ($type eq 'tool') { + %ltitools = &Apache::lonnet::get_domain_ltitools($cdom); + } + $js = &Apache::lonhtmlcommon::scripttag(&extedit_javascript()); my $args = { 'force_register' => $env{'form.register'} }; - return &Apache::loncommon::start_page('External Resource Editor',$js,$args). + my $description = 'External Resource Editor'; + if ($type eq 'tool') { + $description = 'External Tool Editor'; + } + return &Apache::loncommon::start_page($description,$js,$args). '
'. - &extedit_form($supplementalflag,$residx,$url,$title,$pathitem,undef,'direct',$symb). + &extedit_form($supplementalflag,$residx,$url,$title,$pathitem,undef,'direct', + $symb,$type,$cdom,$cnum,\%ltitools). '
'. &Apache::loncommon::end_page(); } sub extedit_javascript { + my ($toolsref) = @_; + my $toolsjs; + if (ref($toolsref) eq 'HASH') { + my $num = scalar(keys(%{$toolsref})); + $toolsjs = " var ltitools = new Array($num);\n". + " var ltitoolsTarget = new Array($num);\n". + " var ltitoolsWidth = new Array($num);\n". + " var ltitoolsHeight = new Array($num);\n"; + my $i = 0; + foreach my $key (sort { $a <=> $b } keys(%{$toolsref})) { + if (ref($toolsref->{$key})) { + my $target = $toolsref->{$key}->{'target'}; + my $width = $toolsref->{$key}->{'width'}; + my $height = $toolsref->{$key}->{'height'}; + $toolsjs .= ' ltitools['.$i.'] = '."'$key';\n". + ' ltitoolsTarget['.$i.'] = '."'$target';\n". + ' ltitoolsWidth['.$i.'] = '."'$width';\n". + ' ltitoolsHeight['.$i.'] = '."'$height';\n"; + $i++; + } + } + } my %js_lt = &Apache::lonlocal::texthash( invurl => 'Invalid URL', titbl => 'Title is blank', + invtool => 'Please select an external tool', ); &js_escape(\%js_lt); @@ -335,40 +575,74 @@ ENDREGEXP var regexp = $urlregexp; -function setExternal(extform,residx) { +function setExternal(extform,residx,type,exttoolurl) { var title=extform.exttitle.value; if (!String.trim) { String.prototype.trim = function() {return this.replace(\/^\\s+|\\s+$\/g, "");}; } - var url=extform.exturl.value; if (title == null || title.trim()=="") { alert("$js_lt{'titbl'}"); extform.exttitle.focus(); return; } - if (regexp.test(url)) { - url = escape(url); + if (type == 'ext') { + var url=extform.exturl.value; + if (!regexp.test(url)) { + alert("$js_lt{'invurl'}"); + extform.exturl.focus(); + return; + } else { + url = escape(url); + title = escape(title); + if (residx > 0) { + eval("extform.importdetail.value=title+'='+url+'='+residx;extform.submit();"); + } else { + eval("extform.importdetail.value=title+'='+url;extform.submit();"); + } + } + } else { title = escape(title); + var info = exttoolurl; + if (residx == 0) { + var toolid = parseInt(extform.exttoolid.options[extform.exttoolid.selectedIndex].value); + if (isNaN(toolid)) { + alert("$js_lt{'invtool'}"); + return; + } + info += ':'+toolid; + } + if (extform.exttooltarget.length) { + for (var i=0; i 0) { - eval("extform.importdetail.value=title+'='+url+'='+residx;extform.submit();"); + eval("extform.importdetail.value=title+'='+info+'='+residx;extform.submit();"); } else { - eval("extform.importdetail.value=title+'='+url;extform.submit();"); + eval("extform.importdetail.value=title+'='+info;extform.submit();"); } - } else { - alert("$js_lt{'invurl'}"); - extform.exturl.focus(); - return; } } -function editext(residx) { - if (document.getElementById('uploadext'+residx)) { - var curr = document.getElementById('uploadext'+residx).style.display; +function editext(residx,type) { + if (document.getElementById('upload'+type+residx)) { + var curr = document.getElementById('upload'+type+residx).style.display; if (curr == 'none') { disp = 'block'; } else { disp = 'none'; } - document.getElementById('uploadext'+residx).style.display=disp; + document.getElementById('upload'+type+residx).style.display=disp; } resize_scrollbox('contentscroll','1','1'); return; @@ -384,6 +658,90 @@ function extUrlPreview(caller) { } } } + +function updateExttool(caller,form,supplementalflag) { + var prefix = ''; + if (supplementalflag == 1) { + prefix = 'supp'; + } + dispdiv = prefix+'tooldispdiv'; + dimendiv = prefix+'tooldimendiv'; + widthinput = prefix+'toolwidth'; + heightinput = prefix+'toolheight'; + if (document.getElementById(dispdiv)) { + var toolpick = caller.options[caller.selectedIndex].value; + $toolsjs + if (toolpick == '') { + if (document.getElementById(dispdiv)) { + document.getElementById(dispdiv).style.display = 'none'; + } + if (document.getElementById(dimendiv)) { + document.getElementById(dimendiv).style.display = 'none'; + } + } else { + if (document.getElementById(dispdiv)) { + document.getElementById(dispdiv).style.display = 'block'; + } + if (ltitools.length > 0) { + for (var j=0; j