--- loncom/interface/londocs.pm 2010/11/28 00:04:05 1.440 +++ loncom/interface/londocs.pm 2014/08/25 01:42:30 1.584 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.440 2010/11/28 00:04:05 raeburn Exp $ +# $Id: londocs.pm,v 1.584 2014/08/25 01:42:30 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,8 +26,6 @@ # http://www.lon-capa.org/ # - - package Apache::londocs; use strict; @@ -41,8 +39,14 @@ use Apache::lonratedt(); use Apache::lonxml; use Apache::lonclonecourse; use Apache::lonnavmaps; +use Apache::lonnavdisplay(); +use Apache::lonextresedit(); +use Apache::lontemplate(); +use Apache::lonsimplepage(); use HTML::Entities; +use HTML::TokeParser; use GDBM_File; +use File::MMagic; use Apache::lonlocal; use Cwd; use LONCAPA qw(:DEFAULT :match); @@ -55,6 +59,7 @@ my $hashtied; my %alreadyseen=(); my $hadchanges; +my $suppchanges; my %help=(); @@ -68,13 +73,21 @@ sub mapread { } sub storemap { - my ($coursenum,$coursedom,$map)=@_; + my ($coursenum,$coursedom,$map,$contentchg)=@_; + my $report; + if (($contentchg) && ($map =~ /^default/)) { + $report = 1; + } my ($outtext,$errtext)= &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'. - $map,1); + $map,1,$report); if ($errtext) { return ($errtext,2); } - $hadchanges=1; + if ($map =~ /^default/) { + $hadchanges=1; + } else { + $suppchanges=1; + } return ($errtext,0); } @@ -101,12 +114,17 @@ sub authorhosts { my $allowed=0; my $myhome=&Apache::lonnet::homeserver($ca,$cd); my @ids=&Apache::lonnet::current_machine_ids(); - foreach my $id (@ids) { if ($id eq $myhome) { $allowed=1; } } + foreach my $id (@ids) { + if ($id eq $myhome) { + $allowed=1; + last; + } + } if ($allowed) { $home++; - $outhash{'home_'.$ca.'@'.$cd}=1; + $outhash{'home_'.$ca.':'.$cd}=1; } else { - $outhash{'otherhome_'.$ca.'@'.$cd}=$myhome; + $outhash{'otherhome_'.$ca.':'.$cd}=$myhome; $other++; } } @@ -115,27 +133,6 @@ sub authorhosts { } -sub dumpbutton { - my ($home,$other,%outhash)=&authorhosts(); - my $crstype = &Apache::loncommon::course_type(); - if ($home+$other==0) { return ''; } - if ($home) { - my $link = - "<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"dumpcourse\", \"" - .&mt('Dump '.$crstype.' Documents to Construction Space') - ."\")'>" - .&mt('Dump '.$crstype.' Documents to Construction Space') - .'</a>'; - return - $link.' ' - .&Apache::loncommon::help_open_topic('Docs_Dump_Course_Docs') - .'<br />'; - } else { - return - &mt('Dump '.$crstype.' Documents to Construction Space: available on other servers'); - } -} - sub clean { my ($title)=@_; $title=~s/[^\w\/\!\$\%\^\*\-\_\=\+\;\:\,\\\|\`\~]+/\_/gs; @@ -147,824 +144,452 @@ sub clean { sub dumpcourse { my ($r) = @_; my $crstype = &Apache::loncommon::course_type(); - $r->print(&Apache::loncommon::start_page('Dump '.$crstype.' Documents to Construction Space'). - '<form name="dumpdoc" action="" method="post">'); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('Dump '.$crstype.' Documents to Construction Space')); + my ($starthash,$js); + unless (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) { + $js = <<"ENDJS"; +<script type="text/javascript"> +// <![CDATA[ + +function hide_searching() { + if (document.getElementById('searching')) { + document.getElementById('searching').style.display = 'none'; + } + return; +} + +// ]]> +</script> +ENDJS + $starthash = { + add_entries => {'onload' => "hide_searching();"}, + }; + } + $r->print(&Apache::loncommon::start_page('Copy '.$crstype.' Content to Authoring Space',$js,$starthash)."\n". + &Apache::lonhtmlcommon::breadcrumbs('Copy '.$crstype.' Content to Authoring Space')."\n"); + $r->print(&startContentScreen('tools')); my ($home,$other,%outhash)=&authorhosts(); - unless ($home) { return ''; } + unless ($home) { + $r->print(&endContentScreen()); + return ''; + } my $origcrsid=$env{'request.course.id'}; my %origcrsdata=&Apache::lonnet::coursedescription($origcrsid); if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) { # Do the dumping - unless ($outhash{'home_'.$env{'form.authorspace'}}) { return ''; } - my ($ca,$cd)=split(/\@/,$env{'form.authorspace'}); + unless ($outhash{'home_'.$env{'form.authorspace'}}) { + $r->print(&endContentScreen()); + return ''; + } + my ($ca,$cd)=split(/\:/,$env{'form.authorspace'}); $r->print('<h3>'.&mt('Copying Files').'</h3>'); my $title=$env{'form.authorfolder'}; $title=&clean($title); - my %replacehash=(); - foreach my $key (keys(%env)) { - if ($key=~/^form\.namefor\_(.+)/) { - $replacehash{$1}=$env{$key}; - } - } - my $crs='/uploaded/'.$env{'request.course.id'}.'/'; - $crs=~s/\_/\//g; - foreach my $item (keys(%replacehash)) { - my $newfilename=$title.'/'.$replacehash{$item}; - $newfilename=~s/\.(\w+)$//; - my $ext=$1; - $newfilename=&clean($newfilename); - $newfilename.='.'.$ext; - my @dirs=split(/\//,$newfilename); - my $path='/home/'.$ca.'/public_html'; - my $makepath=$path; - my $fail=0; - for (my $i=0;$i<$#dirs;$i++) { - $makepath.='/'.$dirs[$i]; - unless (-e $makepath) { - unless(mkdir($makepath,0777)) { $fail=1; } - } - } - $r->print('<br /><tt>'.$item.'</tt> => <tt>'.$newfilename.'</tt>: '); - if (my $fh=Apache::File->new('>'.$path.'/'.$newfilename)) { - if ($item=~/\.(sequence|page|html|htm|xml|xhtml)$/) { - print $fh &Apache::lonclonecourse::rewritefile( - &Apache::lonclonecourse::readfile($env{'request.course.id'},$item), - (%replacehash,$crs => '') - ); - } else { - print $fh - &Apache::lonclonecourse::readfile($env{'request.course.id'},$item); - } - $fh->close(); - } else { - $fail=1; - } - if ($fail) { - $r->print('<span class="LC_error">'.&mt('fail').'</span>'); - } else { - $r->print('<span class="LC_success">'.&mt('ok').'</span>'); - } - } - } else { -# Input form - unless ($home==1) { - $r->print( - '<h3>'.&mt('Select the Construction Space').'</h3><select name="authorspace">'); - } - foreach my $key (sort(keys(%outhash))) { - if ($key=~/^home_(.+)$/) { - if ($home==1) { - $r->print( - '<input type="hidden" name="authorspace" value="'.$1.'" />'); - } else { - $r->print('<option value="'.$1.'">'.$1.' - '. - &Apache::loncommon::plainname(split(/\@/,$1)).'</option>'); - } - } - } - unless ($home==1) { - $r->print('</select>'); - } - my $title=$origcrsdata{'description'}; - $title=~s/[\/\s]+/\_/gs; - $title=&clean($title); - $r->print('<h3>'.&mt('Folder in Construction Space').'</h3>' - .'<input type="text" size="50" name="authorfolder" value="'.$title.'" /><br />'); - &tiehash(); - $r->print('<h3>'.&mt('Filenames in Construction Space').'</h3>' - .&Apache::loncommon::start_data_table() - .&Apache::loncommon::start_data_table_header_row() - .'<th>'.&mt('Internal Filename').'</th>' - .'<th>'.&mt('Title').'</th>' - .'<th>'.&mt('Save as ...').'</th>' - .&Apache::loncommon::end_data_table_header_row()); - foreach my $file (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) { - $r->print(&Apache::loncommon::start_data_table_row() - .'<td>'.$file.'</td>'); - my ($ext)=($file=~/\.(\w+)$/); - my $title=$hash{'title_'.$hash{ - 'ids_/uploaded/'.$origcrsdata{'domain'}.'/'.$origcrsdata{'num'}.'/'.$file}}; - $r->print('<td>'.($title?$title:' ').'</td>'); - if (!$title) { - $title=$file; - } else { - $title=~s|/|_|g; - } - $title=~s/\.(\w+)$//; - $title=&clean($title); - $title.='.'.$ext; - $r->print("\n<td><input type='text' size='60' name='namefor_".$file."' value='".$title."' /></td>" - .&Apache::loncommon::end_data_table_row()); - } - $r->print(&Apache::loncommon::end_data_table()); - &untiehash(); - $r->print( - '<p><input type="submit" name="dumpcourse" value="'.&mt("Dump $crstype Documents").'" /></p></form>'); - } -} - - - -sub exportbutton { - my $crstype = &Apache::loncommon::course_type(); - return "<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"exportcourse\", \"".&mt('IMS Export')."\")'>".&mt('IMS Export')."</a>". - &Apache::loncommon::help_open_topic('Docs_Export_Course_Docs').'<br />'; -} - - - -sub exportcourse { - my $r=shift; - my $crstype = &Apache::loncommon::course_type(); - my %discussiontime = &Apache::lonnet::dump('discussiontimes', - $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'}); - my $numdisc = keys(%discussiontime); - my $navmap = Apache::lonnavmaps::navmap->new(); - if (!defined($navmap)) { - $r->print(&Apache::loncommon::start_page('Export '.$crstype.' to IMS Package'). - '<h2>'.&mt('IMS Export Failed').'</h2>'. - '<div class="LC_error">'); - if ($crstype eq 'Community') { - $r->print(&mt('Unable to retrieve information about community contents')); - } else { - $r->print(&mt('Unable to retrieve information about course contents')); - } - $r->print('</div><a href="/adm/coursedocs">'); - if ($crstype eq 'Community') { - $r->print(&mt('Return to Community Editor')); + my ($navmap,$errormsg) = + &Apache::loncourserespicker::get_navmap_object($crstype,'dumpdocs'); + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my (%maps,%resources,%titles); + if (!ref($navmap)) { + $r->print($errormsg. + &endContentScreen()); + return ''; } else { - $r->print(&mt('Return to Course Editor')); - } - $r->print('</a>'); - &Apache::lonnet::logthis('IMS export failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'}); - return; - } - my $it=$navmap->getIterator(undef,undef,undef,1,undef,undef); - my $curRes; - my $outcome; - - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['finishexport']); - if ($env{'form.finishexport'}) { - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['archive','discussion']); - - my @exportitems = &Apache::loncommon::get_env_multiple('form.archive'); - my @discussions = &Apache::loncommon::get_env_multiple('form.discussion'); - if (@exportitems == 0 && @discussions == 0) { - $outcome = - '<p class="LC_warning">' - .&mt('As you did not select any content items or discussions' - .' for export, an IMS package has not been created.') - .'</p>' - .'<p>' - .&mt('Please [_1]go back[_2] to select either content items' - .' or discussions for export.' - ,'<a href="javascript:history.go(-1)">' - ,'</a>') - .'</p>'; - } else { - my $now = time; - my %symbs; - my $manifestok = 0; - my $imsresources; - my $tempexport; - my $copyresult; - my $ims_manifest = &create_ims_store($now,\$manifestok,\$outcome,\$tempexport); - if ($manifestok) { - &build_package($now,$navmap,\@exportitems,\@discussions,\$outcome,$tempexport,\$copyresult,$ims_manifest); - close($ims_manifest); - -#Create zip file in prtspool - my $imszipfile = '/prtspool/'. - $env{'user.name'}.'_'.$env{'user.domain'}.'_'. - time.'_'.rand(1000000000).'.zip'; - my $cwd = &Cwd::getcwd(); - my $imszip = '/home/httpd/'.$imszipfile; - chdir $tempexport; - open(OUTPUT, "zip -r $imszip * 2> /dev/null |"); - close(OUTPUT); - chdir $cwd; - $outcome .= '<p>' - .&mt('[_1]Your IMS package[_2] is ready for download.' - ,'<a href="'.$imszipfile.'">','</a>') - .'</p>'; - if ($copyresult) { - $outcome .= '<p class="LC_error">' - .&mt('The following errors occurred during export - [_1]' - ,$copyresult) - .'</p>'; - } - } else { - $outcome = '<p class="LC_error">' - .&mt('Unfortunately you will not be able to retrieve' - .' an IMS archive of your course at this time,' - .' because there was a problem creating a' - .' manifest file.') - .'</p>' - .'<p><a href="javascript:history.go(-1)">' - .&mt('Go Back') - .'</a></p>'; - } - } - $r->print(&Apache::loncommon::start_page('Export '.$crstype.' to IMS Package')); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('IMS Export')); - $r->print($outcome); - $r->print(&Apache::loncommon::end_page()); - } else { - my $display='<form name="exportdoc" action="" method="post">'."\n". - '<p>'. - &mt('Choose which items you wish to export from your '.$crstype.'.'). - '</p>'. - '<div class="LC_columnSection"><fieldset>'. - '<legend>'.&mt('Content items').'</legend>'. - '<input type="button" value="'.&mt('check all').'" '. - 'onclick="javascript:checkAll(document.exportdoc.archive)" />'. - ' <input type="button" value="'.&mt('uncheck all').'"'. - ' onclick="javascript:uncheckAll(document.exportdoc.archive)" /></fieldset>'; - if ($numdisc > 0) { - $display .= '<fieldset>'. - '<legend>'.&mt('Discussion posts').'</legend>'. - '<input type="button" value="'.&mt('check all').'"'. - ' onclick="javascript:checkAll(document.exportdoc.discussion)" />'. - ' <input type="button" value="'.&mt('uncheck all').'"'. - ' onclick="javascript:uncheckAll(document.exportdoc.discussion)" />'. - '</fieldset>'; - } - $display .= '</div>'; - my $curRes; - my $depth = 0; - my $count = 0; - my $boards = 0; - my $startcount = 5; - my %parent = (); - my %children = (); - my $lastcontainer = $startcount; - $display .= &Apache::loncommon::start_data_table() - .&Apache::loncommon::start_data_table_header_row() - .'<th>'.&mt('Export content item?').'</th>'; - if ($numdisc > 0) { - $display .= '<th>'.&mt('Export discussion posts?').'</th>'; - } - $display .= &Apache::loncommon::end_data_table_header_row(); - while ($curRes = $it->next()) { - if (ref($curRes)) { - $count ++; - } - if ($curRes == $it->BEGIN_MAP()) { - $depth++; - $parent{$depth} = $lastcontainer; - } - if ($curRes == $it->END_MAP()) { - $depth--; - $lastcontainer = $parent{$depth}; - } - if (ref($curRes)) { - my $symb = $curRes->symb(); - my $ressymb = $symb; - if ($ressymb =~ m|adm/($match_domain)/($match_username)/(\d+)/bulletinboard$|) { - unless ($ressymb =~ m|adm/wrapper/adm|) { - $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard'; - } - } - my $currelem = $count+$boards+$startcount; - $display .= &Apache::loncommon::start_data_table_row() - .'<td>'."\n" - .'<input type="checkbox" name="archive" value="'.$count.'" '; - if (($curRes->is_sequence()) || ($curRes->is_page())) { - $lastcontainer = $currelem; - $display .= 'onclick="javascript:propagateCheck('."'$currelem'".')"'; - } - $display .= ' />'."\n"; - for (my $i=0; $i<$depth; $i++) { - $display .= ('<img src="/adm/lonIcons/whitespace1.gif" class="LC_docs_spacer" alt="" />' x2)."\n"; - } - if ($curRes->is_sequence()) { - $display .= '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" /> '."\n"; - } elsif ($curRes->is_page()) { - $display .= '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" /> '."\n"; - } - $children{$parent{$depth}} .= $currelem.':'; - $display .= ' '.$curRes->title().'</td>'."\n"; - - # Existing discussion posts? - if ($discussiontime{$ressymb} > 0) { - $boards ++; - $display .= '<td align="right">' - .'<input type="checkbox" name="discussion" value="'.$count.'" />' - .'</td>'."\n"; - } elsif ($numdisc > 0) { - $display .= '<td> </td>'."\n"; + &Apache::loncourserespicker::enumerate_course_contents($navmap,\%maps,\%resources,\%titles, + 'dumpdocs',$cdom,$cnum); + } + my @todump = &Apache::loncommon::get_env_multiple('form.archive'); + my (%tocopy,%replacehash,%lookup,%deps,%display,%result,%depresult,%simpleproblems,%simplepages, + %newcontent,%has_simpleprobs); + foreach my $item (sort {$a <=> $b} (@todump)) { + my $name = $env{'form.namefor_'.$item}; + if ($resources{$item}) { + my ($map,$id,$res) = &Apache::lonnet::decode_symb($resources{$item}); + if ($res =~ m{^uploaded/$cdom/$cnum/\E((?:docs|supplemental)/.+)$}) { + $tocopy{$1} = $name; + $display{$item} = $1; + $lookup{$1} = $item; + } elsif ($res eq 'lib/templates/simpleproblem.problem') { + $simpleproblems{$item} = { + symb => $resources{$item}, + name => $name, + }; + $display{$item} = 'simpleproblem_'.$name; + if ($map =~ m{^\Quploaded/$cdom/$cnum/\E(.+)$}) { + $has_simpleprobs{$1}{$id} = $item; + } + } elsif ($res =~ m{^adm/$match_domain/$match_username/(\d+)/smppg}) { + my $marker = $1; + my $db_name = &Apache::lonsimplepage::get_db_name($res,$marker,$cdom,$cnum); + $simplepages{$item} = { + res => $res, + title => $titles{$item}, + db => $db_name, + marker => $marker, + symb => $resources{$item}, + name => $name, + }; + $display{$item} = '/'.$res; + } + } elsif ($maps{$item}) { + if ($maps{$item} =~ m{^\Quploaded/$cdom/$cnum/\E((?:default|supplemental)_\d+\.(?:sequence|page))$}) { + $tocopy{$1} = $name; + $display{$item} = $1; + $lookup{$1} = $item; } - $display .= &Apache::loncommon::end_data_table_row(); + } else { + next; } } - $display .= &Apache::loncommon::end_data_table(); - my $scripttag = qq| -<script type="text/javascript"> -// <![CDATA[ -function checkAll(field) { - if (field.length > 0) { - for (i = 0; i < field.length; i++) { - field[i].checked = true ; - } - } else { - field.checked = true - } -} - -function uncheckAll(field) { - if (field.length > 0) { - for (i = 0; i < field.length; i++) { - field[i].checked = false ; - } - } else { - field.checked = false ; - } -} - -function propagateCheck(item) { - if (document.exportdoc.elements[item].checked == true) { - containerCheck(item) - } -} - -function containerCheck(item) { - document.exportdoc.elements[item].checked = true - var numitems = $count + $boards + $startcount - var parents = new Array(numitems) - for (var i=$startcount; i<numitems; i++) { - parents[i] = new Array - } - |; - - foreach my $container (sort { $a <=> $b } (keys(%children))) { - my @contents = split(/:/,$children{$container}); - for (my $i=0; $i<@contents; $i ++) { - $scripttag .= ' parents['.$container.']['.$i.'] = '.$contents[$i]."\n"; + my $crs='/uploaded/'.$env{'request.course.id'}.'/'; + $crs=~s/\_/\//g; + my $mm = new File::MMagic; + my $prefix = "/uploaded/$cdom/$cnum/"; + %replacehash = %tocopy; + foreach my $item (sort(keys(%simpleproblems))) { + my $content = &Apache::imsexport::simpleproblem($simpleproblems{$item}{'symb'}); + $newcontent{$display{$item}} = $content; + } + my $gateway = Apache::lonhtmlgateway->new('web'); + foreach my $item (sort(keys(%simplepages))) { + if (ref($simplepages{$item}) eq 'HASH') { + my $pagetitle = $simplepages{$item}{'title'}; + my %fields = &Apache::lonnet::dump($simplepages{$item}{'db'},$cdom,$cnum); + my %contents; + foreach my $field (keys(%fields)) { + if ($field =~ /^(?:aaa|bbb|ccc)_(\w+)$/) { + my $name = $1; + my $msg = $fields{$field}; + if ($name eq 'webreferences') { + if ($msg =~ m{^https?://}) { + $contents{$name} = '<a href="'.$msg.'"><tt>'.$msg.'</tt></a>'; + } + } else { + $msg = &Encode::decode('utf8',$msg); + $msg = $gateway->process_outgoing_html($msg,1); + $contents{$name} = $msg; + } + } elsif ($field eq 'uploaded.photourl') { + my $marker = $simplepages{$item}{marker}; + if ($fields{$field} =~ m{^\Q$prefix\E(simplepage/$marker/.+)$}) { + my $filepath = $1; + my ($relpath,$fname) = ($filepath =~ m{^(.+/)([^/]+)$}); + if ($fname ne '') { + $fname=~s/\.(\w+)$//; + my $ext=$1; + $fname = &clean($fname); + $fname.='.'.$ext; + $contents{image} = '<img src="'.$relpath.$fname.'" alt="Image" />'; + $replacehash{$filepath} = $relpath.$fname; + $deps{$item}{$filepath} = 1; + } + } + } + } + $replacehash{'/'.$simplepages{$item}{'res'}} = $simplepages{$item}{'name'}; + $lookup{'/'.$simplepages{$item}{'res'}} = $item; + my $content = ' +<html> +<head> +<title>'.$pagetitle.'</title> +</head> +<body bgcolor="#ffffff">'; + if ($contents{title}) { + $content .= "\n".'<h2>'.$contents{title}.'</h2>'; + } + if ($contents{image}) { + $content .= "\n".$contents{image}; + } + if ($contents{content}) { + $content .= ' +<div class="LC_Box"> +<h4 class="LC_hcell">'.&mt('Content').'</h4>'. +$contents{content}.' +</div>'; + } + if ($contents{webreferences}) { + $content .= ' +<div class="LC_Box"> +<h4 class="LC_hcell">'.&mt('Web References').'</h4>'. +$contents{webreferences}.' +</div>'; + } + $content .= ' +</body> +</html> +'; + $newcontent{'/'.$simplepages{$item}{res}} = $content; } } - - $scripttag .= qq| - if (parents[item].length > 0) { - for (var j=0; j<parents[item].length; j++) { - containerCheck(parents[item][j]) - } - } -} -// ]]> -</script> - |; - $r->print(&Apache::loncommon::start_page('Export '.$crstype.' to IMS Package', - $scripttag)); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('IMS Export')); - $r->print($display. - '<p><input type="hidden" name="finishexport" value="1" />'. - '<input type="submit" name="exportcourse" value="'. - &mt('Export').'" /></p></form>'); - } -} - -sub create_ims_store { - my ($now,$manifestok,$outcome,$tempexport) = @_; - $$tempexport = $Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/ims_exports'; - my $ims_manifest; - if (!-e $$tempexport) { - mkdir($$tempexport,0700); - } - $$tempexport .= '/'.$now; - if (!-e $$tempexport) { - mkdir($$tempexport,0700); - } - $$tempexport .= '/'.$env{'user.domain'}.'_'.$env{'user.name'}; - if (!-e $$tempexport) { - mkdir($$tempexport,0700); - } - if (!-e "$$tempexport/resources") { - mkdir("$$tempexport/resources",0700); - } -# open manifest file - my $manifest = '/imsmanifest.xml'; - my $manifestfilename = $$tempexport.$manifest; - if ($ims_manifest = Apache::File->new('>'.$manifestfilename)) { - $$manifestok=1; - print $ims_manifest -'<?xml version="1.0" encoding="UTF-8"?>'."\n". -'<manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"'. -' xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2"'. -' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'. -' identifier="MANIFEST-'.$env{'request.course.id'}.'-'.$now.'"'. -' xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1imscp_v1p1.xsd'. -' http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd">'."\n". -' <metadata> - <schema></schema> - <imsmd:lom> - <imsmd:general> - <imsmd:identifier>'.$env{'request.course.id'}.'</imsmd:identifier> - <imsmd:title> - <imsmd:langstring xml:lang="en">'.$env{'course.'.$env{'request.course.id'}.'.description'}.'</imsmd:langstring> - </imsmd:title> - </imsmd:general> - </imsmd:lom> - </metadata>'."\n". -' <organizations default="ORG-'.$env{'request.course.id'}.'-'.$now.'">'."\n". -' <organization identifier="ORG-'.$env{'request.course.id'}.'-'.$now.'"'. -' structure="hierarchical">'."\n". -' <title>'.$env{'course.'.$env{'request.course.id'}.'.description'}.'</title>' - } else { - $$outcome .= 'An error occurred opening the IMS manifest file.<br />' -; - } - return $ims_manifest; -} - -sub build_package { - my ($now,$navmap,$exportitems,$discussions,$outcome,$tempexport,$copyresult,$ims_manifest) = @_; -# first iterator to look for dependencies - my $it = $navmap->getIterator(undef,undef,undef,1,undef,undef); - my $curRes; - my $count = 0; - my $depth = 0; - my $lastcontainer = 0; - my %parent = (); - my @dependencies = (); - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - while ($curRes = $it->next()) { - if (ref($curRes)) { - $count ++; - } - if ($curRes == $it->BEGIN_MAP()) { - $depth++; - $parent{$depth} = $lastcontainer; - } - if ($curRes == $it->END_MAP()) { - $depth--; - $lastcontainer = $parent{$depth}; - } - if (ref($curRes)) { - if ($curRes->is_sequence() || $curRes->is_page()) { - $lastcontainer = $count; - } - if (grep(/^$count$/,@$exportitems)) { - &get_dependencies($exportitems,\%parent,$depth,\@dependencies); + foreach my $item (keys(%tocopy)) { + unless ($item=~/\.(sequence|page)$/) { + my $currurlpath = $prefix.$item; + my $currdirpath = &Apache::lonnet::filelocation('',$currurlpath); + &recurse_html($mm,$prefix,$currdirpath,$currurlpath,$item,$lookup{$item},\%replacehash,\%deps); } } - } -# second iterator to build manifest and store resources - $it = $navmap->getIterator(undef,undef,undef,1,undef,undef); - $depth = 0; - my $prevdepth; - $count = 0; - my $imsresources; - my $pkgdepth; - while ($curRes = $it->next()) { - if ($curRes == $it->BEGIN_MAP()) { - $prevdepth = $depth; - $depth++; - } - if ($curRes == $it->END_MAP()) { - $prevdepth = $depth; - $depth--; - } - - if (ref($curRes)) { - $count ++; - if ((grep(/^$count$/,@$exportitems)) || (grep(/^$count$/,@dependencies))) { - my $symb = $curRes->symb(); - my $isvisible = 'true'; - my $resourceref; - if ($curRes->randomout()) { - $isvisible = 'false'; - } - unless ($curRes->is_sequence()) { - $resourceref = 'identifierref="RES-'.$env{'request.course.id'}.'-'.$count.'"'; - } - my $step = $prevdepth - $depth; - if (($step >= 0) && ($count > 1)) { - while ($step >= 0) { - print $ims_manifest "\n".' </item>'."\n"; - $step --; - } - } - $prevdepth = $depth; - - my $itementry = - '<item identifier="ITEM-'.$env{'request.course.id'}.'-'.$count. - '" isvisible="'.$isvisible.'" '.$resourceref.'>'. - '<title>'.$curRes->title().'</title>'; - print $ims_manifest "\n".$itementry; - - unless ($curRes->is_sequence()) { - my $content_file; - my @hrefs = (); - &process_content($count,$curRes,$cdom,$cnum,$symb,\$content_file,\@hrefs,$copyresult,$tempexport); - if ($content_file) { - $imsresources .= "\n". - ' <resource identifier="RES-'.$env{'request.course.id'}.'-'.$count. - '" type="webcontent" href="'.$content_file.'">'."\n". - ' <file href="'.$content_file.'" />'."\n"; - foreach my $item (@hrefs) { - $imsresources .= - ' <file href="'.$item.'" />'."\n"; - } - if (grep(/^$count$/,@$discussions)) { - my $ressymb = $symb; - my $mode; - if ($ressymb =~ m|adm/($match_domain)/($match_username)/(\d+)/bulletinboard$|) { - unless ($ressymb =~ m|adm/wrapper/adm|) { - $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard'; - } - $mode = 'board'; - } - my %extras = ( - caller => 'imsexport', - tempexport => $tempexport.'/resources', - count => $count - ); - my $discresult = &Apache::lonfeedback::list_discussion($mode,undef,$ressymb,\%extras); - } - $imsresources .= ' </resource>'."\n"; - } - } - $pkgdepth = $depth; - } - } - } - while ($pkgdepth > 0) { - print $ims_manifest " </item>\n"; - $pkgdepth --; - } - my $resource_text = qq| - </organization> - </organizations> - <resources> - $imsresources - </resources> -</manifest> - |; - print $ims_manifest $resource_text; -} - -sub get_dependencies { - my ($exportitems,$parent,$depth,$dependencies) = @_; - if ($depth > 1) { - if ((!grep(/^$$parent{$depth}$/,@$exportitems)) && (!grep(/^$$parent{$depth}$/,@$dependencies))) { - push(@{$dependencies},$$parent{$depth}); - if ($depth > 2) { - &get_dependencies($exportitems,$parent,$depth-1,$dependencies); + foreach my $num (sort {$a <=> $b} (@todump)) { + my $src = $display{$num}; + next if ($src eq ''); + my @needcopy = (); + if ($replacehash{$src}) { + push(@needcopy,$src); + if (ref($deps{$num}) eq 'HASH') { + foreach my $dep (sort(keys(%{$deps{$num}}))) { + if ($replacehash{$dep}) { + push(@needcopy,$dep); + } + } + } + } elsif ($src =~ /^simpleproblem_/) { + push(@needcopy,$src); } - } - } -} - -sub process_content { - my ($count,$curRes,$cdom,$cnum,$symb,$content_file,$href,$copyresult,$tempexport) = @_; - my $content_type; - my $message; - my @uploads = (); - if ($curRes->is_sequence()) { - $content_type = 'sequence'; - } elsif ($curRes->is_page()) { - $content_type = 'page'; # need to handle individual items in pages. - } elsif ($symb =~ m-public/$cdom/$cnum/syllabus$-) { - $content_type = 'syllabus'; - my $contents = &Apache::imsexport::templatedpage($content_type); - if ($contents) { - $$content_file = &store_template($contents,$tempexport,$count,$content_type); - } - } elsif ($symb =~ m-\.sequence___\d+___ext-) { - $content_type = 'external'; - my $title = $curRes->title; - my $contents = &Apache::imsexport::external($symb,$title); - if ($contents) { - $$content_file = &store_template($contents,$tempexport,$count,$content_type); - } - } elsif ($symb =~ m-adm/navmaps$-) { - $content_type = 'navmap'; - } elsif ($symb =~ m-adm/[^/]+/[^/]+/(\d+)/smppg$-) { - $content_type = 'simplepage'; - my $contents = &Apache::imsexport::templatedpage($content_type,$1,$count,\@uploads); - if ($contents) { - $$content_file = &store_template($contents,$tempexport,$count,$content_type); - } - } elsif ($symb =~ m-lib/templates/simpleproblem\.problem$-) { - $content_type = 'simpleproblem'; - my $contents = &Apache::imsexport::simpleproblem($symb); - if ($contents) { - $$content_file = &store_template($contents,$tempexport,$count,$content_type); - } - } elsif ($symb =~ m-lib/templates/examupload\.problem$-) { - $content_type = 'examupload'; - } elsif ($symb =~ m-adm/($match_domain)/($match_username)/(\d+)/bulletinboard$-) { - $content_type = 'bulletinboard'; - my $contents = &Apache::imsexport::templatedpage($content_type,$3,$count,\@uploads,$1,$2); - if ($contents) { - $$content_file = &store_template($contents,$tempexport,$count,$content_type); - } - } elsif ($symb =~ m-adm/([^/]+)/([^/]+)/aboutme$-) { - $content_type = 'aboutme'; - my $contents = &Apache::imsexport::templatedpage($content_type,undef,$count,\@uploads,$1,$2); - if ($contents) { - $$content_file = &store_template($contents,$tempexport,$count,$content_type); - } - } elsif ($symb =~ m-\.(sequence|page)___\d+___uploaded/$cdom/$cnum/-) { - $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'uploaded'); - } elsif ($symb =~ m-\.(sequence|page)___\d+___([^/]+)/([^/]+)-) { - my $canedit = 0; - if ($2 eq $env{'user.domain'} && $3 eq $env{'user.name'}) { - $canedit= 1; - } -# only include problem code where current user is author - if ($canedit) { - $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'resource'); - } else { - $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'noedit'); - } - } elsif ($symb =~ m-uploaded/$cdom/$cnum-) { - $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'uploaded'); - } - if (@uploads > 0) { - foreach my $item (@uploads) { - my $uploadmsg = ''; - &replicate_content($cdom,$cnum,$tempexport,$item,$count,\$uploadmsg,$href,'templateupload'); - if ($uploadmsg) { - $$copyresult .= $uploadmsg."\n"; - } - } - } - if ($message) { - $$copyresult .= $message."\n"; - } -} - -sub replicate_content { - my ($cdom,$cnum,$tempexport,$symb,$count,$message,$href,$caller) = @_; - my ($map,$ind,$url); - if ($caller eq 'templateupload') { - $url = $symb; - $url =~ s#//#/#g; - } else { - ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); - } - my $content; - my $filename; - my $repstatus; - my $content_name; - if ($url =~ m-/([^/]+)$-) { - $filename = $1; - if (!-e $tempexport.'/resources') { - mkdir($tempexport.'/resources',0700); - } - if (!-e $tempexport.'/resources/'.$count) { - mkdir($tempexport.'/resources/'.$count,0700); - } - my $destination = $tempexport.'/resources/'.$count.'/'.$filename; - my $copiedfile; - if ($copiedfile = Apache::File->new('>'.$destination)) { - my $content; - if ($caller eq 'resource') { - my $respath = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res'; - my $filepath = &Apache::lonnet::filelocation($respath,$url); - $content = &Apache::lonnet::getfile($filepath); - if ($content eq -1) { - $$message = 'Could not copy file '.$filename; + next if (@needcopy == 0); + my ($result,$depresult); + for (my $i=0; $i<@needcopy; $i++) { + my $item = $needcopy[$i]; + my $newfilename; + if ($simpleproblems{$num}) { + $newfilename=$title.'/'.$simpleproblems{$num}{'name'}; } else { - &extract_media($url,$cdom,$cnum,\$content,$count,$tempexport,$href,$message,'resource'); - $repstatus = 'ok'; + $newfilename=$title.'/'.$replacehash{$item}; } - } elsif ($caller eq 'uploaded' || $caller eq 'templateupload') { - my $rtncode; - $repstatus = &Apache::lonnet::getuploaded('GET',$url,$cdom,$cnum,\$content,$rtncode); - if ($repstatus eq 'ok') { - if ($url =~ /\.html?$/i) { - &extract_media($url,$cdom,$cnum,\$content,$count,$tempexport,$href,$message,'uploaded'); - } + $newfilename=~s/\.(\w+)$//; + my $ext=$1; + $newfilename=&clean($newfilename); + $newfilename.='.'.$ext; + my ($newrelpath) = ($newfilename =~ m{^\Q$title/\E(.+)$}); + if ($newrelpath ne $replacehash{$item}) { + $replacehash{$item} = $newrelpath; + } + my @dirs=split(/\//,$newfilename); + my $path=$r->dir_config('lonDocRoot')."/priv/$cd/$ca"; + my $makepath=$path; + my $fail; + my $origin; + for (my $i=0;$i<$#dirs;$i++) { + $makepath.='/'.$dirs[$i]; + unless (-e $makepath) { + unless(mkdir($makepath,0755)) { + $fail = &mt('Directory creation failed.'); + } + } + } + if ($i == 0) { + $result = '<br /><tt>'.$item.'</tt> => <tt>'.$newfilename.'</tt>: '; } else { - $$message = 'Could not render '.$url.' server message - '.$rtncode."<br />\n"; + $depresult .= '<li><tt>'.$item.'</tt> => <tt>'.$newfilename.'</tt> '. + '<span class="LC_fontsize_small" style="font-weight: bold;">'. + &mt('(dependency)').'</span>: '; + } + if (-e $path.'/'.$newfilename) { + $fail = &mt('Destination already exists -- not overwriting.'); + } else { + if (my $fh=Apache::File->new('>'.$path.'/'.$newfilename)) { + if (($item =~ m{^/adm/$match_domain/$match_username/\d+/smppg}) || + ($item =~ /^simpleproblem_/)) { + print $fh $newcontent{$item}; + } else { + my $fileloc = &Apache::lonnet::filelocation('',$prefix.$item); + if (-e $fileloc) { + if ($item=~/\.(sequence|page|html|htm|xml|xhtml)$/) { + if ((($1 eq 'sequence') || ($1 eq 'page')) && + (ref($has_simpleprobs{$item}) eq 'HASH')) { + my %changes = %{$has_simpleprobs{$item}}; + my $content = &Apache::lonclonecourse::rewritefile( + &Apache::lonclonecourse::readfile($env{'request.course.id'},$item), + (%replacehash,$crs => '') + ); + my $updatedcontent = ''; + my $parser = HTML::TokeParser->new(\$content); + $parser->attr_encoded(1); + while (my $token = $parser->get_token) { + if ($token->[0] eq 'S') { + if (($token->[1] eq 'resource') && + ($token->[2]->{'src'} eq '/res/lib/templates/simpleproblem.problem') && + ($changes{$token->[2]->{'id'}})) { + my $id = $token->[2]->{'id'}; + $updatedcontent .= '<'.$token->[1]; + foreach my $attrib (@{$token->[3]}) { + next unless ($attrib =~ /^(src|type|title|id)$/); + if ($attrib eq 'src') { + my ($file) = ($display{$changes{$id}} =~ /^\Qsimpleproblem_\E(.+)$/); + if ($file) { + $updatedcontent .= ' '.$attrib.'="'.$file.'"'; + } else { + $updatedcontent .= ' '.$attrib.'="'.$token->[2]->{$attrib}.'"'; + } + } else { + $updatedcontent .= ' '.$attrib.'="'.$token->[2]->{$attrib}.'"'; + } + } + $updatedcontent .= ' />'."\n"; + } else { + $updatedcontent .= $token->[4]."\n"; + } + } else { + $updatedcontent .= $token->[2]; + } + } + print $fh $updatedcontent; + } else { + print $fh &Apache::lonclonecourse::rewritefile( + &Apache::lonclonecourse::readfile($env{'request.course.id'},$item), + (%replacehash,$crs => '') + ); + } + } else { + print $fh + &Apache::lonclonecourse::readfile($env{'request.course.id'},$item); + } + } else { + $fail = &mt('Source does not exist.'); + } + } + $fh->close(); + } else { + $fail = &mt('Could not write to destination.'); + } + } + my $text; + if ($fail) { + $text = '<span class="LC_error">'.&mt('fail').(' 'x3).$fail.'</span>'; + } else { + $text = '<span class="LC_success">'.&mt('ok').'</span>'; } - } elsif ($caller eq 'noedit') { -# Need to render the resource without the LON-CAPA Internal header and the Post discussion footer, and then set $content equal to this. - $repstatus = 'ok'; - $content = 'Not the owner of this resource'; + if ($i == 0) { + $result .= $text; + } else { + $depresult .= $text.'</li>'; + } } - if ($repstatus eq 'ok') { - print $copiedfile $content; + $r->print($result); + if ($depresult) { + $r->print('<ul>'.$depresult.'</ul>'); } - close($copiedfile); - } else { - $$message = 'Could not open destination file for '.$filename."<br />\n"; } } else { - $$message = 'Could not determine name of file for '.$symb."<br />\n"; - } - if ($repstatus eq 'ok') { - $content_name = 'resources/'.$count.'/'.$filename; - } - return $content_name; -} - -sub extract_media { - my ($url,$cdom,$cnum,$content,$count,$tempexport,$href,$message,$caller) = @_; - my ($dirpath,$container); - my %allfiles = (); - my %codebase = (); - if ($url =~ m-(.*/)([^/]+)$-) { - $dirpath = $1; - $container = $2; - } else { - $dirpath = $url; - $container = ''; - } - &Apache::lonnet::extract_embedded_items(undef,\%allfiles,\%codebase,$content); - foreach my $embed_file (keys(%allfiles)) { - my $filename; - if ($embed_file =~ m#([^/]+)$#) { - $filename = $1; - } else { - $filename = $embed_file; - } - my $newname = 'res/'.$filename; - my ($rtncode,$embed_content,$repstatus); - my $embed_url; - if ($embed_file =~ m-^/-) { - $embed_url = $embed_file; # points to absolute path + my ($navmap,$errormsg) = + &Apache::loncourserespicker::get_navmap_object($crstype,'dumpdocs'); + if (!ref($navmap)) { + $r->print($errormsg); } else { - if ($embed_file =~ m-https?://-) { - next; # points to url - } else { - $embed_url = $dirpath.$embed_file; # points to relative path + $r->print('<div id="searching">'.&mt('Searching ...').'</div>'); + $r->rflush(); + my ($preamble,$formname); + $formname = 'dumpdoc'; + unless ($home==1) { + $preamble = '<div class="LC_left_float">'. + '<fieldset><legend>'. + &mt('Select the Authoring Space'). + '</legend><select name="authorspace">'; + } + my @orderspaces = (); + foreach my $key (sort(keys(%outhash))) { + if ($key=~/^home_(.+)$/) { + if ($1 eq $env{'user.name'}.':'.$env{'user.domain'}) { + unshift(@orderspaces,$1); + } else { + push(@orderspaces,$1); + } + } } - } - if ($caller eq 'resource') { - my $respath = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res'; - my $embed_path = &Apache::lonnet::filelocation($respath,$embed_url); - $embed_content = &Apache::lonnet::getfile($embed_path); - unless ($embed_content eq -1) { - $repstatus = 'ok'; + if ($home>1) { + $preamble .= '<option value="" selected="selected">'.&mt('Select').'</option>'; } - } elsif ($caller eq 'uploaded') { - - $repstatus = &Apache::lonnet::getuploaded('GET',$embed_url,$cdom,$cnum,\$embed_content,$rtncode); - } - if ($repstatus eq 'ok') { - my $destination = $tempexport.'/resources/'.$count.'/res'; - if (!-e "$destination") { - mkdir($destination,0755); - } - $destination .= '/'.$filename; - my $copiedfile; - if ($copiedfile = Apache::File->new('>'.$destination)) { - print $copiedfile $embed_content; - push(@{$href},'resources/'.$count.'/res/'.$filename); - my $attrib_regexp = ''; - if (@{$allfiles{$embed_file}} > 1) { - $attrib_regexp = join('|',@{$allfiles{$embed_file}}); + foreach my $user (@orderspaces) { + if ($home==1) { + $preamble .= '<input type="hidden" name="authorspace" value="'.$user.'" />'; + } else { + $preamble .= '<option value="'.$user.'">'.$user.' - '. + &Apache::loncommon::plainname(split(/\:/,$user)).'</option>'; + } + } + unless ($home==1) { + $preamble .= '</select></fieldset></div>'."\n"; + } + my $title=$origcrsdata{'description'}; + $title=~s/[\/\s]+/\_/gs; + $title=&clean($title); + $preamble .= '<div class="LC_left_float">'. + '<fieldset><legend>'.&mt('Folder in Authoring Space').'</legend>'. + '<input type="text" size="50" name="authorfolder" value="'. + $title.'" />'. + '</fieldset></div><div style="padding:0;clear:both;margin:0;border:0"></div>'."\n"; + my %uploadedfiles; + &tiehash(); + foreach my $file (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) { + my ($ext)=($file=~/\.(\w+)$/); +# FIXME Check supplemental here + my $title=$hash{'title_'.$hash{ + 'ids_/uploaded/'.$origcrsdata{'domain'}.'/'.$origcrsdata{'num'}.'/'.$file}}; + if (!$title) { + $title=$file; + } else { + $title=~s|/|_|g; + } + $title=~s/\.(\w+)$//; + $title=&clean($title); + $title.='.'.$ext; +# $r->print("\n<td><input type='text' size='60' name='namefor_".$file."' value='".$title."' /></td>" + $uploadedfiles{$file} = $title; + } + &untiehash(); + $r->print(&Apache::loncourserespicker::create_picker($navmap,'dumpdocs',$formname,$crstype,undef, + undef,undef,$preamble,$home,\%uploadedfiles)); + } + } + $r->print(&endContentScreen()); +} + +sub recurse_html { + my ($mm,$prefix,$currdirpath,$currurlpath,$container,$item,$replacehash,$deps) = @_; + return unless ((ref($replacehash) eq 'HASH') && (ref($deps) eq 'HASH')); + my (%allfiles,%codebase); + if (&Apache::lonnet::extract_embedded_items($currdirpath,\%allfiles,\%codebase) eq 'ok') { + if (keys(%allfiles)) { + foreach my $dependency (keys(%allfiles)) { + next if (($dependency =~ m{^/(res|adm)/}) || ($dependency =~ m{^https?://})); + my ($depurl,$relfile,$newcontainer); + if ($dependency =~ m{^/}) { + if ($dependency =~ m{^\Q$currurlpath/\E(.+)$}) { + $relfile = $1; + if ($dependency =~ m{^\Q$prefix\E(.+)$}) { + $newcontainer = $1; + next if ($replacehash->{$newcontainer}); + } + $depurl = $dependency; + } else { + next; + } } else { - $attrib_regexp = $allfiles{$embed_file}[0]; + $relfile = $dependency; + $depurl = $currurlpath; + $depurl =~ s{[^/]+$}{}; + $depurl .= $dependency; + ($newcontainer) = ($depurl =~ m{^\Q$prefix\E(.+)$}); } - $$content =~ s#($attrib_regexp\s*=\s*['"]?)\Q$embed_file\E(['"]?)#$1$newname$2#gi; - if ($caller eq 'resource' && $container =~ /\.(problem|library)$/) { - $$content =~ s#\Q$embed_file\E#$newname#gi; + next if ($relfile eq ''); + my $newname = $replacehash->{$container}; + $newname =~ s{[^/]+$}{}; + $replacehash->{$newcontainer} = $newname.$relfile; + $deps->{$item}{$newcontainer} = 1; + my ($newurlpath) = ($depurl =~ m{^(.*)/[^/]+$}); + my $depfile = &Apache::lonnet::filelocation('',$depurl); + my $type = $mm->checktype_filename($depfile); + if ($type eq 'text/html') { + &recurse_html($mm,$prefix,$depfile,$newurlpath,$newcontainer,$item,$replacehash,$deps); } } - } else { - $$message .= 'replication of embedded file - '.$embed_file.' in '.$url.' failed, reason -'.$rtncode."<br />\n"; } } return; } -sub store_template { - my ($contents,$tempexport,$count,$content_type) = @_; - if ($contents) { - if ($tempexport) { - if (!-e $tempexport.'/resources') { - mkdir($tempexport.'/resources',0700); - } - if (!-e $tempexport.'/resources/'.$count) { - mkdir($tempexport.'/resources/'.$count,0700); - } - my $destination = $tempexport.'/resources/'.$count.'/'.$content_type.'.xml'; - my $storetemplate; - if ($storetemplate = Apache::File->new('>'.$destination)) { - print $storetemplate $contents; - close($storetemplate); - } - if ($content_type eq 'external') { - return 'resources/'.$count.'/'.$content_type.'.html'; - } else { - return 'resources/'.$count.'/'.$content_type.'.xml'; - } - } - } -} - - sub group_import { my ($coursenum, $coursedom, $folder, $container, $caller, @files) = @_; - + my ($donechk,$allmaps,%hierarchy,%titles,%addedmaps,%removefrommap, + %removeparam,$importuploaded,$fixuperrors); + $allmaps = {}; while (@files) { my ($name, $url, $residx) = @{ shift(@files) }; if (($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$}) @@ -981,7 +606,7 @@ sub group_import { $env{'form.output'}=$newmapstr; my $result=&Apache::lonnet::finishuserfileupload($coursenum,$coursedom, 'output',$1.$2); - if ($result != m|^/uploaded/|) { + if ($result !~ m{^/uploaded/}) { $errtext.='Map not saved: A network error occurred when trying to save the new map. '; $fatal = 2; } @@ -990,6 +615,24 @@ sub group_import { } } if ($url) { + if (($caller eq 'londocs') && + ($folder =~ /^default/)) { + if (($url =~ /\.(page|sequence)$/) && (!$donechk)) { + my $chome = &Apache::lonnet::homeserver($coursenum,$coursedom); + my $cid = $coursedom.'_'.$coursenum; + $allmaps = + &Apache::loncommon::allmaps_incourse($coursedom,$coursenum, + $chome,$cid); + $donechk = 1; + } + if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$}) { + &contained_map_check($url,$folder,\%removefrommap,\%removeparam, + \%addedmaps,\%hierarchy,\%titles,$allmaps); + $importuploaded = 1; + } elsif ($url =~ m{^/res/.+\.(page|sequence)$}) { + next if ($allmaps->{$url}); + } + } if (!$residx || defined($LONCAPA::map::zombies[$residx])) { $residx = &LONCAPA::map::getresidx($url,$residx); @@ -997,76 +640,97 @@ sub group_import { } my $ext = 'false'; if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; } - $url = &LONCAPA::map::qtunescape($url); $name = &LONCAPA::map::qtunescape($name); + if ($name eq '') { + $name = &LONCAPA::map::qtunescape(&mt('Web Page')); + } + if ($url =~ m{^/uploaded/$coursedom/$coursenum/((?:docs|supplemental)/(?:default|\d+))/new\.html$}) { + my $filepath = $1; + my $fname = $name; + if ($fname =~ /^\W+$/) { + $fname = 'web'; + } else { + $fname =~ s/\W/_/g; + } + if (length($fname > 15)) { + $fname = substr($fname,0,14); + } + my $initialtext = &mt('Replace with your own content.'); + my $newhtml = <<END; +<html> +<head> +<title>$name</title> +</head> +<body bgcolor="#ffffff"> +$initialtext +</body> +</html> +END + $env{'form.output'}=$newhtml; + my $result = + &Apache::lonnet::finishuserfileupload($coursenum,$coursedom, + 'output', + "$filepath/$residx/$fname.html"); + if ($result =~ m{^/uploaded/}) { + $url = $result; + if ($filepath =~ /^supplemental/) { + $name = time.'___&&&___'.$env{'user.name'}.'___&&&___'. + $env{'user.domain'}.'___&&&___'.$name; + } + } else { + return (&mt('Failed to save new web page.'),1); + } + } + $url = &LONCAPA::map::qtunescape($url); $LONCAPA::map::resources[$residx] = join(':', ($name, $url, $ext, 'normal', 'res')); } } - return &storemap($coursenum, $coursedom, $folder.'.'.$container); -} - -sub breadcrumbs { - my ($allowed,$crstype)=@_; - &Apache::lonhtmlcommon::clear_breadcrumbs(); - my (@folders); - if ($env{'form.pagepath'}) { - @folders = split('&',$env{'form.pagepath'}); - } else { - @folders=split('&',$env{'form.folderpath'}); - } - my $folderpath; - my $cpinfo=''; - my $plain=''; - my $randompick=-1; - my $isencrypted=0; - my $ishidden=0; - my $is_random_order=0; - if (!$allowed) { - my $description = $env{'course.'.$env{'request.course.id'}.'.description'}; - &Apache::lonhtmlcommon::add_breadcrumb( - {'href' => '/adm/menu', - 'title'=> 'Go to main menu', - 'text' => $description, - }); - $plain .= $description.' >'; - } - while (@folders) { - my $folder=shift(@folders); - my $foldername=shift(@folders); - if ($folderpath) {$folderpath.='&';} - $folderpath.=$folder.'&'.$foldername; - my $url='/adm/coursedocs?folderpath='. - &escape($folderpath); - my $name=&unescape($foldername); -# randompick number, hidden, encrypted, random order, is appended with ":"s to the foldername - $name=~s/\:(\d*)\:(\w*)\:(\w*):(\d*)$//; - if ($1 ne '') { - $randompick=$1; - } else { - $randompick=-1; - } - if ($2) { $ishidden=1; } - if ($3) { $isencrypted=1; } - if ($4 ne '') { $is_random_order = 1; } - if ($folder eq 'supplemental') { - $name = &mt('Supplemental '.$crstype.' Documents'); - } - &Apache::lonhtmlcommon::add_breadcrumb( - {'href'=>$url.$cpinfo, - 'title'=>$name, - 'text'=>$name, - 'no_mt'=>1, - }); - $plain.=$name.' > '; - } - $plain=~s/\>\;\s*$//; - return (&Apache::lonhtmlcommon::breadcrumbs(undef,undef,0,'nohelp', - undef, undef, 1 ),$randompick,$ishidden,$isencrypted,$plain,$is_random_order); + if ($importuploaded) { + my %import_errors; + my %updated = ( + removefrommap => \%removefrommap, + removeparam => \%removeparam, + ); + my ($result,$msgsarray,$lockerror) = + &apply_fixups($folder,1,$coursedom,$coursenum,\%import_errors,\%updated); + if (keys(%import_errors) > 0) { + $fixuperrors = + '<p span class="LC_warning">'."\n". + &mt('The following files are either dependencies of a web page or references within a folder and/or composite page for which errors occurred during import:')."\n". + '<ul>'."\n"; + foreach my $key (sort(keys(%import_errors))) { + $fixuperrors .= '<li>'.$key.'</li>'."\n"; + } + $fixuperrors .= '</ul></p>'."\n"; + } + if (ref($msgsarray) eq 'ARRAY') { + if (@{$msgsarray} > 0) { + $fixuperrors .= '<p class="LC_info">'. + join('<br />',@{$msgsarray}). + '</p>'; + } + } + if ($lockerror) { + $fixuperrors .= '<p class="LC_error">'. + $lockerror. + '</p>'; + } + } + my ($errtext,$fatal) = + &storemap($coursenum, $coursedom, $folder.'.'.$container,1); + unless ($fatal) { + if ($folder =~ /^supplemental/) { + &Apache::lonnet::get_numsuppfiles($coursenum,$coursedom,1); + my ($errtext,$fatal) = &mapread($coursenum,$coursedom, + $folder.'.'.$container); + } + } + return ($errtext,$fatal,$fixuperrors); } sub log_docs { - return &Apache::lonnet::instructor_log('docslog',@_); + return &Apache::lonnet::write_log('course','docslog',@_); } { @@ -1126,39 +790,71 @@ sub log_docs { } } - - - - sub docs_change_log { - my ($r)=@_; - my $folder=$env{'form.folder'}; - $r->print(&Apache::loncommon::start_page('Course Document Change Log')); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Document Change Log')); + my ($r,$coursenum,$coursedom,$folder,$allowed,$crstype,$iconpath)=@_; + my $supplementalflag=($env{'form.folderpath'}=~/^supplemental/); + my $js = '<script type="text/javascript">'."\n". + '// <![CDATA['."\n". + &Apache::loncommon::display_filter_js('docslog')."\n". + &editing_js($env{'user.domain'},$env{'user.name'},$supplementalflag)."\n". + &history_tab_js()."\n". + &Apache::lonratedt::editscript('simple')."\n". + '// ]]>'."\n". + '</script>'."\n"; + $r->print(&Apache::loncommon::start_page('Content Change Log',$js)); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content Change Log')); + $r->print(&startContentScreen(($supplementalflag?'suppdocs':'docs'))); + my %orderhash; + my $container='sequence'; + my $pathitem; + if ($env{'form.folderpath'} =~ /\:1$/) { + $container='page'; + } + my $folderpath=$env{'form.folderpath'}; + if ($folderpath eq '') { + $folderpath = 'default&'.&escape(&mt('Main Content').':::::'); + } + $pathitem = '<input type="hidden" name="folderpath" value="'. + &HTML::Entities::encode($folderpath,'<>&"').'" />'; + my $readfile="/uploaded/$coursedom/$coursenum/$folder.$container"; + my $jumpto = $readfile; + $jumpto =~ s{^/}{}; + my $tid = 1; + if ($supplementalflag) { + $tid = 2; + } + my ($breadcrumbtrail) = + &Apache::lonhtmlcommon::docs_breadcrumbs($allowed,$crstype,1); + $r->print($breadcrumbtrail. + &generate_edit_table($tid,\%orderhash,undef,$iconpath,$jumpto, + $readfile)); my %docslog=&Apache::lonnet::dump('nohist_docslog', $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'}); if ((keys(%docslog))[0]=~/^error\:/) { undef(%docslog); } - $r->print('<form action="/adm/coursedocs" method="post" name="docslog">'. - '<input type="hidden" name="docslog" value="1" />'); - my %saveable_parameters = ('show' => 'scalar',); &Apache::loncommon::store_course_settings('docs_log', \%saveable_parameters); &Apache::loncommon::restore_course_settings('docs_log', \%saveable_parameters); if (!$env{'form.show'}) { $env{'form.show'}=10; } +# FIXME: internationalization seems wrong here my %lt=('hiddenresource' => 'Resources hidden', 'encrypturl' => 'URL hidden', 'randompick' => 'Randomly pick', 'randomorder' => 'Randomly ordered', 'set' => 'set to', 'del' => 'deleted'); - $r->print(&Apache::loncommon::display_filter(). - '<input type="hidden" name="folder" value="'.$folder.'" />'. - '<input type="submit" value="'.&mt('Display').'" /></form>'); + my $filter = &Apache::loncommon::display_filter('docslog')."\n". + $pathitem."\n". + '<input type="hidden" name="folder" value="'.$env{'form.folder'}.'" />'. + (' 'x2).'<input type="submit" value="'.&mt('Display').'" />'; + $r->print('<div class="LC_left_float">'. + '<fieldset><legend>'.&mt('Display of Content Changes').'</legend>'."\n". + &makedocslogform($filter,1). + '</fieldset></div><br clear="all" />'); $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row(). '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Folder').'</th><th>'.&mt('Before').'</th><th>'. &mt('After').'</th>'. @@ -1202,18 +898,30 @@ sub docs_change_log { ':'.$docslog{$id}{'exe_udom'}.'</tt>'. $send_msg_link.'</td><td>'. $docslog{$id}{'logentry'}{'folder'}.'</td><td>'); + my $is_supp = 0; + if ($docslog{$id}{'logentry'}{'currentfolder'} =~ /^supplemental/) { + $is_supp = 1; + } # Before for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) { my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0]; my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0]; if ($oldname ne $newname) { - $r->print(&LONCAPA::map::qtescape($oldname)); + my $shown = &LONCAPA::map::qtescape($oldname); + if ($is_supp) { + $shown = &Apache::loncommon::parse_supplemental_title($shown); + } + $r->print($shown); } } $r->print('<ul>'); for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) { if ($docslog{$id}{'logentry'}{'before_order_res_'.$idx}) { - $r->print('<li>'.&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'before_order_res_'.$idx}))[0]).'</li>'); + my $shown = &LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'before_order_res_'.$idx}))[0]); + if ($is_supp) { + $shown = &Apache::loncommon::parse_supplemental_title($shown); + } + $r->print('<li>'.$shown.'</li>'); } } $r->print('</ul>'); @@ -1224,13 +932,21 @@ sub docs_change_log { my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0]; my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0]; if ($oldname ne '' && $oldname ne $newname) { - $r->print(&LONCAPA::map::qtescape($newname)); + my $shown = &LONCAPA::map::qtescape($newname); + if ($is_supp) { + $shown = &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($newname)); + } + $r->print($shown); } } $r->print('<ul>'); for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) { if ($docslog{$id}{'logentry'}{'after_order_res_'.$idx}) { - $r->print('<li>'.&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'after_order_res_'.$idx}))[0]).'</li>'); + my $shown = &LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'after_order_res_'.$idx}))[0]); + if ($is_supp) { + $shown = &Apache::loncommon::parse_supplemental_title($shown); + } + $r->print('<li>'.$shown.'</li>'); } } $r->print('</ul>'); @@ -1238,6 +954,7 @@ sub docs_change_log { $r->print(&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'}))[0]).':<ul>'); foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder') { if ($docslog{$id}{'logentry'}{'parameter_action_'.$parameter}) { +# FIXME: internationalization seems wrong here $r->print('<li>'. &mt($lt{$parameter}.' '.$lt{$docslog{$id}{'logentry'}{'parameter_action_'.$parameter}}.' [_1]', $docslog{$id}{'logentry'}{'parameter_value_'.$parameter}) @@ -1252,171 +969,1032 @@ sub docs_change_log { if (!($env{'form.show'} eq &mt('all') || $shown<=$env{'form.show'})) { last; } } - $r->print(&Apache::loncommon::end_data_table()); + $r->print(&Apache::loncommon::end_data_table()."\n". + &makesimpleeditform($pathitem)."\n". + '</div></div>'); + $r->print(&endContentScreen()); } sub update_paste_buffer { - my ($coursenum,$coursedom) = @_; + my ($coursenum,$coursedom,$folder) = @_; + my (@possibles,%removals,%cuts); + if ($env{'form.multiremove'}) { + $env{'form.multiremove'} =~ s/,$//; + map { $removals{$_} = 1; } split(/,/,$env{'form.multiremove'}); + } + if (($env{'form.multicopy'}) || ($env{'form.multicut'})) { + if ($env{'form.multicut'}) { + $env{'form.multicut'} =~ s/,$//; + foreach my $item (split(/,/,$env{'form.multicut'})) { + unless ($removals{$item}) { + $cuts{$item} = 1; + push(@possibles,$item.':cut'); + } + } + } + if ($env{'form.multicopy'}) { + $env{'form.multicopy'} =~ s/,$//; + foreach my $item (split(/,/,$env{'form.multicopy'})) { + unless ($removals{$item} || $cuts{$item}) { + push(@possibles,$item.':copy'); + } + } + } + } elsif ($env{'form.markcopy'}) { + @possibles = split(/,/,$env{'form.markcopy'}); + } - return if (!defined($env{'form.markcopy'})); + return if (@possibles == 0); return if (!defined($env{'form.copyfolder'})); - return if ($env{'form.markcopy'} < 0); my ($errtext,$fatal) = &mapread($coursenum,$coursedom, $env{'form.copyfolder'}); - return if ($fatal); -# Mark for copying - my ($title,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$env{'form.markcopy'}]]); - if (&is_supplemental_title($title)) { - &Apache::lonnet::appenv({'docs.markedcopy_supplemental' => $title}); - ($title) = &parse_supplemental_title($title); - } elsif ($env{'docs.markedcopy_supplemental'}) { - &Apache::lonnet::delenv('docs.markedcopy_supplemental'); + my %curr_groups = &Apache::longroup::coursegroups(); + +# Retrieve current paste buffer suffixes. + my @currpaste = split(/,/,$env{'docs.markedcopies'}); + my (%pasteurls,@newpaste); + +# Construct identifiers for current contents of user's paste buffer + if (@currpaste) { + foreach my $suffix (@currpaste) { + my $cid = $env{'docs.markedcopy_crs_'.$suffix}; + my $url = $env{'docs.markedcopy_url_'.$suffix}; + if (($cid =~ /^$match_domain(?:_)$match_courseid$/) && + ($url ne '')) { + $pasteurls{$cid.'_'.$url} = 1; + } + } } - $url=~s{http(:|:)//https(:|:)//}{https$2//}; - &Apache::lonnet::appenv({'docs.markedcopy_title' => $title, - 'docs.markedcopy_url' => $url}); +# Mark items for copying (skip any items already in user's paste buffer) + my %addtoenv; + + foreach my $item (@possibles) { + my ($orderidx,$cmd) = split(/:/,$item); + next if ($orderidx =~ /\D/); + next unless (($cmd eq 'cut') || ($cmd eq 'copy') || ($cmd eq 'remove')); + my ($title,$url)=split(':',$LONCAPA::map::resources[$orderidx]); + my %denied = &action_restrictions($coursenum,$coursedom, + &LONCAPA::map::qtescape($url), + $env{'form.folderpath'},\%curr_groups); + next if ($denied{'copy'}); + $url=~s{http(:|:)//https(:|:)//}{https$2//}; + next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$url})); + my ($suffix,$errortxt,$locknotfreed) = + &new_timebased_suffix($env{'user.domain'},$env{'user.name'},'paste'); + push(@newpaste,$suffix); + if ($locknotfreed) { + return $locknotfreed; + last; + } + if (&is_supplemental_title($title)) { + &Apache::lonnet::appenv({'docs.markedcopy_supplemental_'.$suffix => $title}); + ($title) = &Apache::loncommon::parse_supplemental_title($title); + } + + $addtoenv{'docs.markedcopy_title_'.$suffix} = $title, + $addtoenv{'docs.markedcopy_url_'.$suffix} = $url, + $addtoenv{'docs.markedcopy_cmd_'.$suffix} = $cmd, + $addtoenv{'docs.markedcopy_crs_'.$suffix} = $env{'request.course.id'}; + + if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(default|supplemental)_?(\d*)\.(page|sequence)$}) { + my $prefix = $1; + my $subdir =$2; + if ($subdir eq '') { + $subdir = $prefix; + } + my (%addedmaps,%removefrommap,%removeparam,%hierarchy,%titles,%allmaps); + &contained_map_check($url,$folder,\%removefrommap,\%removeparam,\%addedmaps, + \%hierarchy,\%titles,\%allmaps); + if (ref($hierarchy{$url}) eq 'HASH') { + my ($nested,$nestednames); + &recurse_uploaded_maps($url,$subdir,\%hierarchy,\%titles,\$nested,\$nestednames); + $nested =~ s/\&$//; + $nestednames =~ s/\Q___&&&___\E$//; + if ($nested ne '') { + $addtoenv{'docs.markedcopy_nested_'.$suffix} = $nested; + } + if ($nestednames ne '') { + $addtoenv{'docs.markedcopy_nestednames_'.$suffix} = $nestednames; + } + } + } + } + if (@newpaste) { + $addtoenv{'docs.markedcopies'} = join(',',(@currpaste,@newpaste)); + } + &Apache::lonnet::appenv(\%addtoenv); delete($env{'form.markcopy'}); + return; +} + +sub recurse_uploaded_maps { + my ($url,$dir,$hierarchy,$titlesref,$nestref,$namesref) = @_; + if (ref($hierarchy->{$url}) eq 'HASH') { + my @maps = map { $hierarchy->{$url}{$_}; } sort { $a <=> $b } (keys(%{$hierarchy->{$url}})); + my @titles = map { $titlesref->{$url}{$_}; } sort { $a <=> $b } (keys(%{$titlesref->{$url}})); + my (@uploaded,@names,%shorter); + for (my $i=0; $i<@maps; $i++) { + my ($inner) = ($maps[$i] =~ m{^/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_(\d+)\.(?:page|sequence)$}); + if ($inner ne '') { + push(@uploaded,$inner); + push(@names,&escape($titles[$i])); + $shorter{$maps[$i]} = $inner; + } + } + $$nestref .= "$dir:".join(',',@uploaded).'&'; + $$namesref .= "$dir:".(join(',',@names)).'___&&&___'; + foreach my $map (@maps) { + if ($shorter{$map} ne '') { + &recurse_uploaded_maps($map,$shorter{$map},$hierarchy,$titlesref,$nestref,$namesref); + } + } + } + return; } sub print_paste_buffer { - my ($r,$container) = @_; - return if (!defined($env{'docs.markedcopy_url'})); + my ($r,$container,$folder,$coursedom,$coursenum) = @_; + return if (!defined($env{'docs.markedcopies'})); - $r->print('<fieldset>' - .'<legend>'.&mt('Clipboard').'</legend>' - .'<form name="pasteform" action="/adm/coursedocs" method="post">' - .'<input type="submit" name="pastemarked" value="'.&mt('Paste').'" /> ' - ); + unless (($env{'form.pastemarked'}) || ($env{'form.clearmarked'})) { + return if ($env{'docs.markedcopies'} eq ''); + } - my $type; - if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) { - $type = &mt('External Resource'); - $r->print($type.': '. - &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('. - &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')'); - } else { - my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1]; - my $icon = &Apache::loncommon::icon($extension); - if ($extension eq 'sequence' && - $env{'docs.markedcopy_url'} =~ m{/default_\d+\.sequence$ }x) { - $icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL')); - $icon .= '/navmap.folder.closed.gif'; - } - $icon = '<img src="'.$icon.'" alt="" class="LC_icon" />'; - $r->print($icon.$type.': '. &parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}))); + my @currpaste = split(/,/,$env{'docs.markedcopies'}); + my ($pasteitems,@pasteable); + my $clipboardcount = 0; + +# Construct identifiers for current contents of user's paste buffer + foreach my $suffix (@currpaste) { + next if ($suffix =~ /\D/); + my $cid = $env{'docs.markedcopy_crs_'.$suffix}; + my $url = $env{'docs.markedcopy_url_'.$suffix}; + if (($cid =~ /^$match_domain\_$match_courseid$/) && + ($url ne '')) { + $clipboardcount ++; + my ($is_external,$othercourse,$fromsupp,$is_uploaded_map,$parent, + $canpaste,$nopaste,$othercrs,$areachange); + my $extension = (split(/\./,$env{'docs.markedcopy_url_'.$suffix}))[-1]; + if ($url =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) { + $is_external = 1; + } + if ($folder =~ /^supplemental/) { + $canpaste = &supp_pasteable($env{'docs.markedcopy_url_'.$suffix}); + unless ($canpaste) { + $nopaste = &mt('Paste into Supplemental Content unavailable.'); + } + } else { + $canpaste = 1; + } + if ($canpaste) { + if ($url =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)$}) { + my $srcdom = $1; + my $srcnum = $2; + my $rem = $3; + if (($srcdom ne $coursedom) || ($srcnum ne $coursenum)) { + $othercourse = 1; + if ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) { + if ($canpaste) { + $othercrs = '<br />'.&mt('(from another course)'); + } + } else { + $canpaste = 0; + $nopaste = &mt('Paste from another course unavailable.'); + } + } + if ($rem =~ m{^(default|supplemental)_?(\d*)\.(?:page|sequence)$}) { + my $prefix = $1; + $parent = $2; + if ($folder !~ /^\Q$prefix\E/) { + $areachange = 1; + } + $is_uploaded_map = 1; + } + } + } + if ($canpaste) { + push(@pasteable,$suffix); + } + my $buffer; + if ($is_external) { + $buffer = &mt('External Resource').': '. + &LONCAPA::map::qtescape($env{'docs.markedcopy_title_'.$suffix}).' ('. + &LONCAPA::map::qtescape($url).')'; + } else { + my $icon = &Apache::loncommon::icon($extension); + if ($extension eq 'sequence' && + $url =~ m{/default_\d+\.sequence$}x) { + $icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL')); + $icon .= '/navmap.folder.closed.gif'; + } + $buffer = '<img src="'.$icon.'" alt="" class="LC_icon" />'. + ': '. + &Apache::loncommon::parse_supplemental_title( + &LONCAPA::map::qtescape($env{'docs.markedcopy_title_'.$suffix})); + } + $pasteitems .= '<div class="LC_left_float">'; + my ($options,$onclick); + if (($canpaste) && (!$areachange) && (!$othercourse) && + ($env{'docs.markedcopy_cmd_'.$suffix} eq 'cut')) { + if (($is_uploaded_map) || + ($url =~ /(bulletinboard|smppg)$/) || + ($url =~ m{^/uploaded/$coursedom/$coursenum/(?:docs|supplemental)/(.+)$})) { + $options = &paste_options($suffix,$is_uploaded_map,$parent); + $onclick= 'onclick="showOptions(this,'."'$suffix'".');" '; + } + } + $pasteitems .= '<label><input type="checkbox" name="pasting" id="pasting_'.$suffix.'" value="'.$suffix.'" '.$onclick.'/>'.$buffer.'</label>'; + if ($nopaste) { + $pasteitems .= $nopaste; + } else { + if ($othercrs) { + $pasteitems .= $othercrs; + } + if ($options) { + $pasteitems .= $options; + } + } + $pasteitems .= '</div>'; + } } - if ($container eq 'page') { - $r->print(' - <input type="hidden" name="pagepath" value="'.&HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" /> - <input type="hidden" name="pagesymb" value="'.&HTML::Entities::encode($env{'form.pagesymb'},'<>&"').'" /> -'); + if ($pasteitems eq '') { + &Apache::lonnet::delenv('docs.markedcopies'); + } + my ($pasteform,$form_start,$buttons,$form_end); + if ($pasteitems) { + $pasteitems .= '<div style="padding:0;clear:both;margin:0;border:0"></div>'; + $form_start = '<form name="pasteform" action="/adm/coursedocs" method="post" onsubmit="return validateClipboard();">'; + if (@pasteable) { + my $value = &mt('Paste to current folder'); + if ($container eq 'page') { + $value = &mt('Paste to current page'); + } + $buttons = '<input type="submit" name="pastemarked" value="'.$value.'" />'.(' 'x2); + } + $buttons .= '<input type="submit" name="clearmarked" value="'.&mt('Remove from clipboard').'" />'.(' 'x2); + if ($clipboardcount > 1) { + $buttons .= + '<span style="text-decoration:line-through">'.(' 'x20).'</span>'.(' 'x2). + '<input type="button" name="checkallclip" value="'.&mt('Check all').'" style="height:20px;" onclick="checkClipboard();" />'. + (' 'x2). + '<input type="button" name="uncheckallclip" value="'.&mt('Uncheck all').'" style="height:20px;" onclick="uncheckClipboard();" />'. + (' 'x2); + } + $form_end = '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />'. + '</form>'; } else { - $r->print(' - <input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" /> -'); + $pasteitems = &mt('Clipboard is empty'); + } + $r->print($form_start + .'<fieldset>' + .'<legend>'.&mt('Clipboard').(' ' x2).$buttons.'</legend>' + .$pasteitems + .'</fieldset>' + .$form_end); +} + +sub paste_options { + my ($suffix,$is_uploaded_map,$parent) = @_; + my ($copytext,$movetext); + if ($is_uploaded_map) { + $copytext = &mt('Copy to new folder'); + $movetext = &mt('Move old'); + } elsif ($env{'docs.markedcopy_url_'.$suffix} =~ /bulletinboard$/) { + $copytext = &mt('Copy to new board'); + $movetext = &mt('Move (not posts)'); + } elsif ($env{'docs.markedcopy_url_'.$suffix} =~ /smppg$/) { + $copytext = &mt('Copy to new page'); + $movetext = &mt('Move'); + } else { + $copytext = &mt('Copy to new file'); + $movetext = &mt('Move'); + } + my $output = '<br />'. + '<span id="pasteoptionstext_'.$suffix.'" class="LC_fontsize_small LC_nobreak"></span>'. + '<div id="pasteoptions_'.$suffix.'" class="LC_dccid" style="display:none;"><span class="LC_nobreak">'.(' 'x 4). + '<label>'. + '<input type="radio" name="docs.markedcopy_options_'.$suffix.'" value="new" checked="checked" />'. + $copytext.'</label></span>'.(' 'x2).' '. + '<span class="LC_nobreak"><label>'. + '<input type="radio" name="docs.markedcopy_options_'.$suffix.'" value="move" />'. + $movetext.'</label></span>'; + if (($is_uploaded_map) && ($env{'docs.markedcopy_nested_'.$suffix})) { + $output .= '<br /><fieldset><legend>'.&mt('Folder to paste contains sub-folders'). + '</legend><table border="0">'; + my @pastemaps = split(/\&/,$env{'docs.markedcopy_nested_'.$suffix}); + my @titles = split(/\Q___&&&___\E/,$env{'docs.markedcopy_nestednames_'.$suffix}); + my $lastdir = $parent; + my %depths = ( + $lastdir => 0, + ); + my (%display,%deps); + for (my $i=0; $i<@pastemaps; $i++) { + ($lastdir,my $subfolderstr) = split(/\:/,$pastemaps[$i]); + my ($namedir,$esctitlestr) = split(/\:/,$titles[$i]); + my @subfolders = split(/,/,$subfolderstr); + $deps{$lastdir} = \@subfolders; + my @subfoldertitles = map { &unescape($_); } split(/,/,$esctitlestr); + my $depth = $depths{$lastdir} + 1; + my $offset = int($depth * 4); + my $indent = (' ' x $offset); + for (my $j=0; $j<@subfolders; $j++) { + $depths{$subfolders[$j]} = $depth; + $display{$subfolders[$j]} = + '<tr><td>'.$indent.$subfoldertitles[$j].' </td>'. + '<td><label>'. + '<input type="radio" name="docs.markedcopy_'.$suffix.'_'.$subfolders[$j].'" value="new" checked="checked" />'.&mt('Copy to new').'</label>'.(' ' x2). + '<label>'. + '<input type="radio" name="docs.markedcopy_'.$suffix.'_'.$subfolders[$j].'" value="move" />'. + &mt('Move old').'</label>'. + '</td></tr>'; + } + } + &recurse_print(\$output,$parent,\%deps,\%display); + $output .= '</table></fieldset>'; + } + $output .= '</div>'; + return $output; +} + +sub recurse_print { + my ($outputref,$dir,$deps,$display) = @_; + $$outputref .= $display->{$dir}."\n"; + if (ref($deps->{$dir}) eq 'ARRAY') { + foreach my $subdir (@{$deps->{$dir}}) { + &recurse_print($outputref,$subdir,$deps,$display); + } + } +} + +sub supp_pasteable { + my ($url) = @_; + if (($url =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//}) || + (($url =~ /\.sequence$/) && ($url =~ m{^/uploaded/})) || + ($url =~ m{^/uploaded/$match_domain/$match_courseid/(docs|supplemental)/(default|\d+)/\d+/}) || + ($url =~ m{^/adm/$match_domain/$match_username/aboutme}) || + ($url =~ m{^/public/$match_domain/$match_courseid/syllabus})) { + return 1; + } + return; +} + +sub paste_popup_js { + my %lt = &Apache::lonlocal::texthash( + show => 'Show Options', + hide => 'Hide Options', + none => 'No items selected from clipboard.', + ); + return <<"END"; + +function showPasteOptions(suffix) { + document.getElementById('pasteoptions_'+suffix).style.display='block'; + document.getElementById('pasteoptionstext_'+suffix).innerHTML = ' <a href="javascript:hidePasteOptions(\\''+suffix+'\\');" class="LC_menubuttons_link">$lt{'hide'}</a>'; + return; +} + +function hidePasteOptions(suffix) { + document.getElementById('pasteoptions_'+suffix).style.display='none'; + document.getElementById('pasteoptionstext_'+suffix).innerHTML =' <a href="javascript:showPasteOptions(\\''+suffix+'\\')" class="LC_menubuttons_link">$lt{'show'}</a>'; + return; +} + +function showOptions(caller,suffix) { + if (document.getElementById('pasteoptionstext_'+suffix)) { + if (caller.checked) { + document.getElementById('pasteoptionstext_'+suffix).innerHTML =' <a href="javascript:showPasteOptions(\\''+suffix+'\\')" class="LC_menubuttons_link">$lt{'show'}</a>'; + } else { + document.getElementById('pasteoptionstext_'+suffix).innerHTML =''; + } + if (document.getElementById('pasteoptions_'+suffix)) { + document.getElementById('pasteoptions_'+suffix).style.display='none'; + } } - $r->print('</form></fieldset>'); + return; +} + +function validateClipboard() { + var numchk = 0; + if (document.pasteform.pasting.length > 1) { + for (var i=0; i<document.pasteform.pasting.length; i++) { + if (document.pasteform.pasting[i].checked) { + numchk ++; + } + } + } else { + if (document.pasteform.pasting.type == 'checkbox') { + if (document.pasteform.pasting.checked) { + numchk ++; + } + } + } + if (numchk > 0) { + return true; + } else { + alert("$lt{'none'}"); + return false; + } +} + +function checkClipboard() { + if (document.pasteform.pasting.length > 1) { + for (var i=0; i<document.pasteform.pasting.length; i++) { + document.pasteform.pasting[i].checked = true; + } + } + return; +} + +function uncheckClipboard() { + if (document.pasteform.pasting.length >1) { + for (var i=0; i<document.pasteform.pasting.length; i++) { + document.pasteform.pasting[i].checked = false; + } + } + return; +} + +END + } sub do_paste_from_buffer { - my ($coursenum,$coursedom,$folder) = @_; + my ($coursenum,$coursedom,$folder,$container,$errors) = @_; - if (!$env{'form.pastemarked'}) { - return; +# Array of items in paste buffer + my (@currpaste,%pastebuffer,%allerrors); + @currpaste = split(/,/,$env{'docs.markedcopies'}); + +# Early out if paste buffer is empty + if (@currpaste == 0) { + return (); + } + map { $pastebuffer{$_} = 1; } @currpaste; + +# Array of items selected items to paste + my @reqpaste = &Apache::loncommon::get_env_multiple('form.pasting'); + +# Early out if nothing selected to paste + if (@reqpaste == 0) { + return(); + } + my @topaste; + foreach my $suffix (@reqpaste) { + next if ($suffix =~ /\D/); + next unless (exists($pastebuffer{$suffix})); + push(@topaste,$suffix); } -# paste resource to end of list - my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url'}); - my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}); +# Early out if nothing available to paste + if (@topaste == 0) { + return(); + } + + my (%msgs,%before,%after,@dopaste,%is_map,%notinsupp,%notincrs,%duplicate, + %prefixchg,%srcdom,%srcnum,%marktomove,$save_err,$lockerrors,$allresult); + + foreach my $suffix (@topaste) { + my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url_'.$suffix}); +# Supplemental content may only include certain types of content +# Early out if pasted content is not supported in Supplemental area + if ($folder =~ /^supplemental/) { + unless (&supp_pasteable($url)) { + $notinsupp{$suffix} = 1; + next; + } + } + if ($url =~ m{^/uploaded/($match_domain)/($match_courseid)/}) { + my $srcd = $1; + my $srcn = $2; +# When paste buffer was populated using an active role in a different course +# check for mdc privilege in the course from which the resource was pasted + if (($srcd ne $coursedom) || ($srcn ne $coursenum)) { + unless ($env{"user.priv.cm./$srcd/$srcn"} =~ /\Q:mdc&F\E/) { + $notincrs{$suffix} = 1; + next; + } + } + $srcdom{$suffix} = $srcd; + $srcnum{$suffix} = $srcn; + } + + push(@dopaste,$suffix); + if ($url=~/\.(page|sequence)$/) { + $is_map{$suffix} = 1; + } + + if ($url =~ m{^/uploaded/$match_domain/$match_courseid/([^/]+)}) { + my $oldprefix = $1; +# When pasting content from Main Content to Supplemental Content and vice versa +# URLs will contain different paths (which depend on whether pasted item is +# a folder/page or a document. + if (($folder =~ /^supplemental/) && (($oldprefix =~ /^default/) || ($oldprefix eq 'docs'))) { + $prefixchg{$suffix} = 'docstosupp'; + } elsif (($folder =~ /^default/) && ($oldprefix =~ /^supplemental/)) { + $prefixchg{$suffix} = 'supptodocs'; + } + +# If pasting an uploaded map, get list of contained uploaded maps. + if ($env{'docs.markedcopy_nested_'.$suffix}) { + my @nested; + my ($type) = ($oldprefix =~ /^(default|supplemental)/); + my @items = split(/\&/,$env{'docs.markedcopy_nested_'.$suffix}); + my @deps = map { /\d+:([\d,]+$)/ } @items; + foreach my $dep (@deps) { + if ($dep =~ /,/) { + push(@nested,split(/,/,$dep)); + } else { + push(@nested,$dep); + } + } + foreach my $item (@nested) { + if ($env{'form.docs.markedcopy_'.$suffix.'_'.$item} eq 'move') { + push(@{$marktomove{$suffix}},$type.'_'.$item); + } + } + } + } + } + +# Early out if nothing available to paste + if (@dopaste == 0) { + return (); + } + +# Populate message hash and hashes used for main content <=> supplemental content +# changes + + %msgs = &Apache::lonlocal::texthash ( + notinsupp => 'Paste failed: content type is not supported within Supplemental Content', + notincrs => 'Paste failed: Item is from a different course which you do not have rights to edit.', + duplicate => 'Paste failed: only one instance of a particular published sequence or page is allowed within each course.', + ); + + %before = ( + docstosupp => { + map => 'default', + doc => 'docs', + }, + supptodocs => { + map => 'supplemental', + doc => 'supplemental', + }, + ); + + %after = ( + docstosupp => { + map => 'supplemental', + doc => 'supplemental' + }, + supptodocs => { + map => 'default', + doc => 'docs', + }, + ); + +# Retrieve information about all course maps in main content area + + my $allmaps = {}; + if ($folder =~ /^default/) { + $allmaps = + &Apache::loncommon::allmaps_incourse($coursedom,$coursenum, + $env{"course.$env{'request.course.id'}.home"}, + $env{'request.course.id'}); + } + + my (@toclear,%mapurls,%lockerrs,%msgerrs,%results); + +# Loop over the items to paste + foreach my $suffix (@dopaste) { # Maps need to be copied first - if (($url=~/\.(page|sequence)$/) && ($url=~/^\/uploaded\//)) { - $title=&mt('Copy of').' '.$title; - my $newid=$$.int(rand(100)).time; - my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/); - if ($oldid =~ m{^(/uploaded/\Q$coursedom\E/\Q$coursenum\E/)(\D+)(\d+)$}) { - my $path = $1; - my $prefix = $2; - my $ancestor = $3; - if (length($ancestor) > 10) { - $ancestor = substr($ancestor,-10,10); + my (%removefrommap,%removeparam,%addedmaps,%rewrites,%retitles,%copies, + %dbcopies,%zombies,%params,%docmoves,%mapmoves,%mapchanges,%newsubdir, + %newurls,%tomove); + if (ref($marktomove{$suffix}) eq 'ARRAY') { + map { $tomove{$_} = 1; } @{$marktomove{$suffix}}; + } + my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url_'.$suffix}); + my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title_'.$suffix}); + my $oldurl = $url; + if ($is_map{$suffix}) { +# If pasting a map, check if map contains other maps + my (%hierarchy,%titles); + &contained_map_check($url,$folder,\%removefrommap,\%removeparam, + \%addedmaps,\%hierarchy,\%titles,$allmaps); + if ($url=~ m{^/uploaded/}) { + my $newurl; + unless ($env{'form.docs.markedcopy_options_'.$suffix} eq 'move') { + ($newurl,my $error) = + &get_newmap_url($url,$folder,$prefixchg{$suffix},$coursedom, + $coursenum,$srcdom{$suffix},$srcnum{$suffix}, + \$title,$allmaps,\%newurls); + if ($error) { + $allerrors{$suffix} = $error; + next; + } + if ($newurl ne '') { + if ($newurl ne $url) { + if ($newurl =~ /(?:default|supplemental)_(\d+).(?:sequence|page)$/) { + $newsubdir{$url} = $1; + } + $mapchanges{$url} = 1; + } + } + } + if (($srcdom{$suffix} ne $coursedom) || + ($srcnum{$suffix} ne $coursenum) || + ($prefixchg{$suffix}) || (($newurl ne '') && ($newurl ne $url))) { + unless (&url_paste_fixups($url,$folder,$prefixchg{$suffix}, + $coursedom,$coursenum,$srcdom{$suffix}, + $srcnum{$suffix},$allmaps,\%rewrites, + \%retitles,\%copies,\%dbcopies, + \%zombies,\%params,\%mapmoves, + \%mapchanges,\%tomove,\%newsubdir, + \%newurls)) { + $mapmoves{$url} = 1; + } + $url = $newurl; + } elsif ($env{'docs.markedcopy_nested_'.$suffix}) { + &url_paste_fixups($url,$folder,$prefixchg{$suffix},$coursedom, + $coursenum,$srcdom{$suffix},$srcnum{$suffix}, + $allmaps,\%rewrites,\%retitles,\%copies,\%dbcopies, + \%zombies,\%params,\%mapmoves,\%mapchanges, + \%tomove,\%newsubdir,\%newurls); + } + } elsif ($url=~m {^/res/}) { +# published map can only exists once, so remove from paste buffer when done + push(@toclear,$suffix); +# if pasting published map (main content area only) check map not already in course + if ($folder =~ /^default/) { + if ((ref($allmaps) eq 'HASH') && ($allmaps->{$url})) { + $duplicate{$suffix} = 1; + next; + } + } + } + } + if ($url=~ m{/(bulletinboard|smppg)$}) { + my $prefix = $1; + #need to copy the db contents to a new one, unless this is a move. + my %info = ( + src => $url, + cdom => $coursedom, + cnum => $coursenum, + ); + unless ($env{'form.docs.markedcopy_options_'.$suffix} eq 'move') { + my (%lockerr,$msg); + my ($newurl,$result,$errtext) = + &dbcopy(\%info,$coursedom,$coursenum,\%lockerr); + if ($result eq 'ok') { + $url = $newurl; + $title=&mt('Copy of').' '.$title; + } else { + if ($prefix eq 'smppg') { + $msg = &mt('Paste failed: An error occurred when copying the simple page.').' '.$errtext; + } elsif ($prefix eq 'bulletinboard') { + $msg = &mt('Paste failed: An error occurred when copying the discussion board.').' '.$errtext; + } + $results{$suffix} = $result; + $msgerrs{$suffix} = $msg; + $lockerrs{$suffix} = $lockerr{$prefix}; + next; + } + if ($lockerr{$prefix}) { + $lockerrs{$suffix} = $lockerr{$prefix}; + } + } + } + $title = &LONCAPA::map::qtunescape($title); + my $ext='false'; + if ($url=~m{^http(|s)://}) { $ext='true'; } + if ($env{'docs.markedcopy_supplemental_'.$suffix}) { + if ($folder !~ /^supplemental/) { + (undef,undef,$title) = + &Apache::loncommon::parse_supplemental_title($env{'docs.markedcopy_supplemental_'.$suffix}); + } + } else { + if ($folder=~/^supplemental/) { + $title=time.'___&&&___'.$env{'user.name'}.'___&&&___'. + $env{'user.domain'}.'___&&&___'.$title; } - $oldid = $path.$prefix.$ancestor; + } + +# For uploaded files (excluding pages/sequences) path in copied file is changed +# if paste is from Main to Supplemental (or vice versa), or if pasting between +# courses. + + unless ($is_map{$suffix}) { + my $newidx; +# Now insert the URL at the bottom + $newidx = &LONCAPA::map::getresidx(&LONCAPA::map::qtunescape($url)); + if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(.+)$}) { + my $relpath = $1; + if ($relpath ne '') { + my ($prefix,$subdir,$rem) = ($relpath =~ m{^(default|\d+)/(\d+)/(.+)$}); + my ($newloc,$newdocsdir) = ($folder =~ /^(default|supplemental)_?(\d*)/); + my $newprefix = $newloc; + if ($newloc eq 'default') { + $newprefix = 'docs'; + } + if ($newdocsdir eq '') { + $newdocsdir = 'default'; + } + if (($prefixchg{$suffix}) || + ($srcdom{$suffix} ne $coursedom) || + ($srcnum{$suffix} ne $coursenum) || + ($env{'form.docs.markedcopy_options_'.$suffix} ne 'move')) { + my $newpath = "$newprefix/$newdocsdir/$newidx/$rem"; + $url = + &Apache::lonclonecourse::writefile($env{'request.course.id'},$newpath, + &Apache::lonnet::getfile($oldurl)); + if ($url eq '/adm/notfound.html') { + $msgs{$suffix} = &mt('Paste failed: an error occurred saving the file.'); + next; + } else { + my ($newsubpath) = ($newpath =~ m{^(.*/)[^/]*$}); + $newsubpath =~ s{/+$}{/}; + $docmoves{$oldurl} = $newsubpath; + } + } + } + } + $LONCAPA::map::resources[$newidx]=$title.':'.&LONCAPA::map::qtunescape($url). + ':'.$ext.':normal:res'; + push(@LONCAPA::map::order,$newidx); +# Store the result + my ($errtext,$fatal) = + &storemap($coursenum,$coursedom,$folder.'.'.$container,1); + if ($fatal) { + $save_err .= $errtext; + $allresult = 'fail'; + } + } + +# Apply any changes to maps, or copy dependencies for uploaded HTML pages + unless ($allresult eq 'fail') { + my %updated = ( + rewrites => \%rewrites, + zombies => \%zombies, + removefrommap => \%removefrommap, + removeparam => \%removeparam, + dbcopies => \%dbcopies, + retitles => \%retitles, + ); + my %info = ( + newsubdir => \%newsubdir, + params => \%params, + ); + if ($prefixchg{$suffix}) { + $info{'before'} = $before{$prefixchg{$suffix}}; + $info{'after'} = $after{$prefixchg{$suffix}}; + } + my %moves = ( + copies => \%copies, + docmoves => \%docmoves, + mapmoves => \%mapmoves, + ); + (my $result,$msgs{$suffix},my $lockerror) = + &apply_fixups($folder,$is_map{$suffix},$coursedom,$coursenum,$errors, + \%updated,\%info,\%moves,$prefixchg{$suffix},$oldurl, + $url,'paste'); + $lockerrors .= $lockerror; + if ($result eq 'ok') { + if ($is_map{$suffix}) { + my ($errtext,$fatal) = &mapread($coursenum,$coursedom, + $folder.'.'.$container); + if ($fatal) { + $allresult = 'failread'; + } else { + if ($#LONCAPA::map::order<1) { + my $idx=&LONCAPA::map::getresidx(); + if ($idx<=0) { $idx=1; } + $LONCAPA::map::order[0]=$idx; + $LONCAPA::map::resources[$idx]=''; + } + my $newidx = &LONCAPA::map::getresidx(&LONCAPA::map::qtunescape($url)); + $LONCAPA::map::resources[$newidx]=$title.':'.&LONCAPA::map::qtunescape($url). + ':'.$ext.':normal:res'; + push(@LONCAPA::map::order,$newidx); + +# Store the result + my ($errtext,$fatal) = + &storemap($coursenum,$coursedom,$folder.'.'.$container,1); + if ($fatal) { + $save_err .= $errtext; + $allresult = 'failstore'; + } + } + } + if ($env{'form.docs.markedcopy_options_'.$suffix} eq 'move') { + push(@toclear,$suffix); + } + } + } + } + &clear_from_buffer(\@toclear,\@currpaste); + my $msgsarray; + foreach my $suffix (keys(%msgs)) { + if (ref($msgs{$suffix}) eq 'ARRAY') { + $msgsarray .= join(',',@{$msgs{$suffix}}); + } + } + return ($allresult,$save_err,$msgsarray,$lockerrors); +} + +sub do_buffer_empty { + my @currpaste = split(/,/,$env{'docs.markedcopies'}); + if (@currpaste == 0) { + return &mt('Clipboard is already empty'); + } + my @toclear = &Apache::loncommon::get_env_multiple('form.pasting'); + if (@toclear == 0) { + return &mt('Nothing selected to clear from clipboard'); + } + my $numdel = &clear_from_buffer(\@toclear,\@currpaste); + if ($numdel) { + return &mt('[quant,_1,item] cleared from clipboard',$numdel); + } else { + return &mt('Clipboard unchanged'); + } + return; +} + +sub clear_from_buffer { + my ($toclear,$currpaste) = @_; + return unless ((ref($toclear) eq 'ARRAY') && (ref($currpaste) eq 'ARRAY')); + my %pastebuffer; + map { $pastebuffer{$_} = 1; } @{$currpaste}; + my $numdel = 0; + foreach my $suffix (@{$toclear}) { + next if ($suffix =~ /\D/); + next unless (exists($pastebuffer{$suffix})); + my $regexp = 'docs.markedcopy_[a-z]+_'.$suffix; + if (&Apache::lonnet::delenv($regexp,1) eq 'ok') { + delete($pastebuffer{$suffix}); + $numdel ++; + } + } + my $newbuffer = join(',',sort(keys(%pastebuffer))); + &Apache::lonnet::appenv({'docs.markedcopies' => $newbuffer}); + return $numdel; +} + +sub get_newmap_url { + my ($url,$folder,$prefixchg,$coursedom,$coursenum,$srcdom,$srcnum, + $titleref,$allmaps,$newurls) = @_; + my $newurl; + if ($url=~ m{^/uploaded/}) { + $$titleref=&mt('Copy of').' '.$$titleref; + } + my $now = time; + my $suffix=$$.int(rand(100)).$now; + my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/); + if ($oldid =~ m{^(/uploaded/$match_domain/$match_courseid/)(\D+)(\d+)$}) { + my $path = $1; + my $prefix = $2; + my $ancestor = $3; + if (length($ancestor) > 10) { + $ancestor = substr($ancestor,-10,10); + } + my $newid; + if ($prefixchg) { + if ($folder =~ /^supplemental/) { + $prefix =~ s/^default/supplemental/; + } else { + $prefix =~ s/^supplemental/default/; + } + } + if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) { + $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext; + } else { + $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$now.'.'.$ext; } my $counter = 0; - my $newurl=$oldid.$newid.'.'.$ext; my $is_unique = &uniqueness_check($newurl); - while (!$is_unique && $counter < 100) { - $counter ++; - $newid ++; - $newurl = $oldid.$newid; - $is_unique = &uniqueness_check($newurl); + if ($folder =~ /^default/) { + if ($allmaps->{$newurl}) { + $is_unique = 0; + } } - if (!$is_unique) { - if ($url=~/\.page$/) { - return &mt('Paste failed: an error occurred creating a unique URL for the composite page'); + while ((!$is_unique || $allmaps->{$newurl} || $newurls->{$newurl}) && ($counter < 100)) { + $counter ++; + $suffix ++; + if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) { + $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext; } else { - return &mt('Paste failed: an error occurred creating a unique URL for the folder'); + $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$ancestor.$suffix.'.'.$ext; } + $is_unique = &uniqueness_check($newurl); } - my $storefn=$newurl; - $storefn=~s{^/\w+/$match_domain/$match_username/}{}; - my $paste_map_result = - &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn, - &Apache::lonnet::getfile($url)); - if ($paste_map_result eq '/adm/notfound.html') { + if ($is_unique) { + $newurls->{$newurl} = 1; + } else { if ($url=~/\.page$/) { - return &mt('Paste failed: an error occurred saving the composite page'); + return (undef,&mt('Paste failed: an error occurred creating a unique URL for the composite page')); } else { - return &mt('Paste failed: an error occurred saving the folder'); + return (undef,&mt('Paste failed: an error occurred creating a unique URL for the folder')); } } - $url = $newurl; } -# published maps can only exists once, so remove it from paste buffer when done - if (($url=~/\.(page|sequence)$/) && ($url=~m {^/res/})) { - &Apache::lonnet::delenv('docs.markedcopy'); - } - if ($url=~ m{/smppg$}) { - my $db_name = &Apache::lonsimplepage::get_db_name($url); - if ($db_name =~ /^smppage_/) { - #simple pages, need to copy the db contents to a new one. - my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum); - my $now = time(); - $db_name =~ s{_\d*$ }{_$now}x; - my $result=&Apache::lonnet::put($db_name,\%contents, - $coursedom,$coursenum); - $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x; - $title=&mt('Copy of').' '.$title; - } - } - $title = &LONCAPA::map::qtunescape($title); - my $ext='false'; - if ($url=~m{^http(|s)://}) { $ext='true'; } - $url = &LONCAPA::map::qtunescape($url); -# Now insert the URL at the bottom - my $newidx = &LONCAPA::map::getresidx($url); - if ($env{'docs.markedcopy_supplemental'}) { - if ($folder =~ /^supplemental/) { - $title = $env{'docs.markedcopy_supplemental'}; - } else { - (undef,undef,$title) = - &parse_supplemental_title($env{'docs.markedcopy_supplemental'}); - } - } else { - if ($folder=~/^supplemental/) { - $title=time.'___&&&___'.$env{'user.name'}.'___&&&___'. - $env{'user.domain'}.'___&&&___'.$title; + return ($newurl); +} + +sub dbcopy { + my ($dbref,$coursedom,$coursenum,$lockerrorsref) = @_; + my ($url,$result,$errtext); + $url = $dbref->{'src'}; + if (ref($dbref) eq 'HASH') { + if ($url =~ m{/(smppg|bulletinboard)$}) { + my $prefix = $1; + if (($dbref->{'cdom'} =~ /^$match_domain$/) && + ($dbref->{'cnum'} =~ /^$match_courseid$/)) { + my $db_name; + my $marker = (split(m{/},$url))[4]; + $marker=~s/\D//g; + if ($dbref->{'src'} =~ m{/smppg$}) { + $db_name = + &Apache::lonsimplepage::get_db_name($url,$marker, + $dbref->{'cdom'}, + $dbref->{'cnum'}); + } else { + $db_name = 'bulletinpage_'.$marker; + } + my ($suffix,$freedlock,$error) = + &Apache::lonnet::get_timebased_id($prefix,'num','templated', + $coursedom,$coursenum, + 'concat'); + if (!$suffix) { + if ($prefix eq 'smppg') { + $errtext = &mt('Failed to acquire a unique timestamp-based suffix when copying a simple page [_1].',$url); + } else { + $errtext = &mt('Failed to acquire a unique timestamp-based suffix when copying a discussion board [_1].',$url); + } + if ($error) { + $errtext .= '<br />'.$error; + } + } else { + #need to copy the db contents to a new one. + my %contents=&Apache::lonnet::dump($db_name, + $dbref->{'cdom'}, + $dbref->{'cnum'}); + if (exists($contents{'uploaded.photourl'})) { + my $photo = $contents{'uploaded.photourl'}; + my ($subdir,$fname) = + ($photo =~ m{^/uploaded/$match_domain/$match_courseid/+(bulletin|simplepage)/(?:|\d+/)([^/]+)$}); + my $newphoto; + if ($fname ne '') { + my $content = &Apache::lonnet::getfile($photo); + unless ($content eq '-1') { + $env{'form.'.$suffix.'.photourl'} = $content; + $newphoto = + &Apache::lonnet::finishuserfileupload($coursenum,$coursedom,$suffix.'.photourl',"$subdir/$suffix/$fname"); + delete($env{'form.'.$suffix.'.photourl'}); + } + } + if ($newphoto =~ m{^/uploaded/}) { + $contents{'uploaded.photourl'} = $newphoto; + } + } + $db_name =~ s{_\d*$ }{_$suffix}x; + $result=&Apache::lonnet::put($db_name,\%contents, + $coursedom,$coursenum); + if ($result eq 'ok') { + $url =~ s{/(\d*)/(smppg|bulletinboard)$}{/$suffix/$2}x; + } + } + if (($freedlock ne 'ok') && (ref($lockerrorsref) eq 'HASH')) { + $lockerrorsref->{$prefix} = + '<div class="LC_error">'. + &mt('There was a problem removing a lockfile.'); + if ($prefix eq 'smppg') { + $lockerrorsref->{$prefix} .= + ' '.&mt('This will prevent creation of additional simple pages in this course.'); + } else { + $lockerrorsref->{$prefix} .= ' '.&mt('This will prevent creation of additional discussion boards in this course.'); + } + $lockerrorsref->{$prefix} .= ' '.&mt('Please contact the [_1]helpdesk[_2] for assistance.', + '<a href="/adm/helpdesk" target="_helpdesk">','</a>'). + '</div>'; + } + } + } elsif ($url =~ m{/syllabus$}) { + if (($dbref->{'cdom'} =~ /^$match_domain$/) && + ($dbref->{'cnum'} =~ /^$match_courseid$/)) { + if (($dbref->{'cdom'} ne $coursedom) || + ($dbref->{'cnum'} ne $coursenum)) { + my %contents=&Apache::lonnet::dump('syllabus', + $dbref->{'cdom'}, + $dbref->{'cnum'}); + $result=&Apache::lonnet::put('syllabus',\%contents, + $coursedom,$coursenum); + } + } } } - - $LONCAPA::map::resources[$newidx]= $title.':'.$url.':'.$ext.':normal:res'; - push(@LONCAPA::map::order, $newidx); - return 'ok'; -# Store the result + return ($url,$result,$errtext); } sub uniqueness_check { @@ -1433,6 +2011,519 @@ sub uniqueness_check { return $unique; } +sub contained_map_check { + my ($url,$folder,$removefrommap,$removeparam,$addedmaps,$hierarchy,$titles, + $allmaps) = @_; + my $content = &Apache::lonnet::getfile($url); + unless ($content eq '-1') { + my $parser = HTML::TokeParser->new(\$content); + $parser->attr_encoded(1); + while (my $token = $parser->get_token) { + next if ($token->[0] ne 'S'); + if ($token->[1] eq 'resource') { + next if ($token->[2]->{'type'} eq 'zombie'); + my $ressrc = $token->[2]->{'src'}; + if ($folder =~ /^supplemental/) { + unless (&supp_pasteable($ressrc)) { + $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; + next; + } + } + if ($ressrc =~ m{^/(res|uploaded)/.+\.(sequence|page)$}) { + if ($1 eq 'uploaded') { + $hierarchy->{$url}{$token->[2]->{'id'}} = $ressrc; + $titles->{$url}{$token->[2]->{'id'}} = $token->[2]->{'title'}; + } else { + if ($allmaps->{$ressrc}) { + $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; + } elsif (ref($addedmaps->{$ressrc}) eq 'ARRAY') { + $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; + } else { + $addedmaps->{$ressrc} = [$url]; + } + } + &contained_map_check($ressrc,$folder,$removefrommap,$removeparam, + $addedmaps,$hierarchy,$titles,$allmaps); + } + } elsif ($token->[1] eq 'param') { + if ($folder =~ /^supplemental/) { + if (ref($removeparam->{$url}{$token->[2]->{'to'}}) eq 'ARRAY') { + push(@{$removeparam->{$url}{$token->[2]->{'to'}}},$token->[2]->{'name'}); + } else { + $removeparam->{$url}{$token->[2]->{'to'}} = [$token->[2]->{'name'}]; + } + } + } + } + } + return; +} + +sub url_paste_fixups { + my ($oldurl,$folder,$prefixchg,$cdom,$cnum,$fromcdom,$fromcnum,$allmaps, + $rewrites,$retitles,$copies,$dbcopies,$zombies,$params,$mapmoves, + $mapchanges,$tomove,$newsubdir,$newurls) = @_; + my $checktitle; + if (($prefixchg) && + ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/supplemental})) { + $checktitle = 1; + } + my $skip; + if ($oldurl =~ m{^\Q/uploaded/$cdom/$cnum/\E(default|supplemental)(_?\d*)\.(?:page|sequence)$}) { + my $mapid = $1.$2; + if ($tomove->{$mapid}) { + $skip = 1; + } + } + my $file = &Apache::lonnet::getfile($oldurl); + return if ($file eq '-1'); + my $parser = HTML::TokeParser->new(\$file); + $parser->attr_encoded(1); + my $changed = 0; + while (my $token = $parser->get_token) { + next if ($token->[0] ne 'S'); + if ($token->[1] eq 'resource') { + my $ressrc = $token->[2]->{'src'}; + next if ($ressrc eq ''); + my $id = $token->[2]->{'id'}; + my $title = $token->[2]->{'title'}; + if ($checktitle) { + if ($title =~ m{\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) { + $retitles->{$oldurl}{$id} = $ressrc; + } + } + next if ($token->[2]->{'type'} eq 'external'); + if ($token->[2]->{'type'} eq 'zombie') { + next if ($skip); + $zombies->{$oldurl}{$id} = $ressrc; + $changed = 1; + } elsif ($ressrc =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)$}) { + my $srcdom = $1; + my $srcnum = $2; + my $rem = $3; + my $newurl; + my $mapname; + if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) { + my $prefix = $1; + $mapname = $prefix.$2; + if ($tomove->{$mapname}) { + &url_paste_fixups($ressrc,$folder,$prefixchg,$cdom,$cnum, + $srcdom,$srcnum,$allmaps,$rewrites, + $retitles,$copies,$dbcopies,$zombies, + $params,$mapmoves,$mapchanges,$tomove, + $newsubdir,$newurls); + next; + } else { + ($newurl,my $error) = + &get_newmap_url($ressrc,$folder,$prefixchg,$cdom,$cnum, + $srcdom,$srcnum,\$title,$allmaps,$newurls); + if ($newurl =~ /(?:default|supplemental)_(\d+)\.(?:sequence|page)$/) { + $newsubdir->{$ressrc} = $1; + } + if ($error) { + next; + } + } + } + if (($srcdom ne $cdom) || ($srcnum ne $cnum) || ($prefixchg) || + ($mapchanges->{$oldurl}) || (($newurl ne '') && ($newurl ne $oldurl))) { + + if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) { + $rewrites->{$oldurl}{$id} = $ressrc; + $mapchanges->{$ressrc} = 1; + unless (&url_paste_fixups($ressrc,$folder,$prefixchg,$cdom, + $cnum,$srcdom,$srcnum,$allmaps, + $rewrites,$retitles,$copies,$dbcopies, + $zombies,$params,$mapmoves,$mapchanges, + $tomove,$newsubdir,$newurls)) { + $mapmoves->{$ressrc} = 1; + } + $changed = 1; + } else { + $rewrites->{$oldurl}{$id} = $ressrc; + $copies->{$oldurl}{$ressrc} = $id; + $changed = 1; + } + } + } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/.+$}) { + next if ($skip); + my $srcdom = $1; + my $srcnum = $2; + if (($srcdom ne $cdom) || ($srcnum ne $cnum)) { + $rewrites->{$oldurl}{$id} = $ressrc; + $dbcopies->{$oldurl}{$id}{'src'} = $ressrc; + $dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom; + $dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum; + $changed = 1; + } + } elsif ($ressrc =~ m{^/adm/$match_domain/$match_username/\d+/(smppg|bulletinboard)$}) { + if (($fromcdom ne $cdom) || ($fromcnum ne $cnum) || + ($env{'form.docs.markedcopy_options'} ne 'move')) { + $dbcopies->{$oldurl}{$id}{'src'} = $ressrc; + $dbcopies->{$oldurl}{$id}{'cdom'} = $fromcdom; + $dbcopies->{$oldurl}{$id}{'cnum'} = $fromcnum; + $changed = 1; + } + } elsif ($ressrc =~ m{^/public/($match_domain)/($match_courseid)/(.+)$}) { + next if ($skip); + my $srcdom = $1; + my $srcnum = $2; + if (($srcdom ne $cdom) || ($srcnum ne $cnum)) { + $dbcopies->{$oldurl}{$id}{'src'} = $ressrc; + $dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom; + $dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum; + $changed = 1; + } + } + } elsif ($token->[1] eq 'param') { + next if ($skip); + my $to = $token->[2]->{'to'}; + if ($to ne '') { + if (ref($params->{$oldurl}{$to}) eq 'ARRAY') { + push(@{$params->{$oldurl}{$to}},$token->[2]->{'name'}); + } else { + @{$params->{$oldurl}{$to}} = ($token->[2]->{'name'}); + } + } + } + } + return $changed; +} + +sub apply_fixups { + my ($folder,$is_map,$cdom,$cnum,$errors,$updated,$info,$moves,$prefixchg, + $oldurl,$url,$caller) = @_; + my (%rewrites,%zombies,%removefrommap,%removeparam,%dbcopies,%retitles, + %params,%newsubdir,%before,%after,%copies,%docmoves,%mapmoves,@msgs, + %lockerrors,$lockmsg); + if (ref($updated) eq 'HASH') { + if (ref($updated->{'rewrites'}) eq 'HASH') { + %rewrites = %{$updated->{'rewrites'}}; + } + if (ref($updated->{'zombies'}) eq 'HASH') { + %zombies = %{$updated->{'zombies'}}; + } + if (ref($updated->{'removefrommap'}) eq 'HASH') { + %removefrommap = %{$updated->{'removefrommap'}}; + } + if (ref($updated->{'removeparam'}) eq 'HASH') { + %removeparam = %{$updated->{'removeparam'}}; + } + if (ref($updated->{'dbcopies'}) eq 'HASH') { + %dbcopies = %{$updated->{'dbcopies'}}; + } + if (ref($updated->{'retitles'}) eq 'HASH') { + %retitles = %{$updated->{'retitles'}}; + } + } + if (ref($info) eq 'HASH') { + if (ref($info->{'newsubdir'}) eq 'HASH') { + %newsubdir = %{$info->{'newsubdir'}}; + } + if (ref($info->{'params'}) eq 'HASH') { + %params = %{$info->{'params'}}; + } + if (ref($info->{'before'}) eq 'HASH') { + %before = %{$info->{'before'}}; + } + if (ref($info->{'after'}) eq 'HASH') { + %after = %{$info->{'after'}}; + } + } + if (ref($moves) eq 'HASH') { + if (ref($moves->{'copies'}) eq 'HASH') { + %copies = %{$moves->{'copies'}}; + } + if (ref($moves->{'docmoves'}) eq 'HASH') { + %docmoves = %{$moves->{'docmoves'}}; + } + if (ref($moves->{'mapmoves'}) eq 'HASH') { + %mapmoves = %{$moves->{'mapmoves'}}; + } + } + foreach my $key (keys(%copies),keys(%docmoves)) { + my @allcopies; + if (exists($copies{$key})) { + if (ref($copies{$key}) eq 'HASH') { + my %added; + foreach my $innerkey (keys(%{$copies{$key}})) { + if (($innerkey ne '') && (!$added{$innerkey})) { + push(@allcopies,$innerkey); + $added{$innerkey} = 1; + } + } + undef(%added); + } + } + if ($key eq $oldurl) { + if ((exists($docmoves{$key}))) { + unless (grep(/^\Q$oldurl\E$/,@allcopies)) { + push(@allcopies,$oldurl); + } + } + } + if (@allcopies > 0) { + foreach my $item (@allcopies) { + my ($relpath,$oldsubdir,$fname) = + ($item =~ m{^(/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(default|\d+)/.*/)([^/]+)$}); + if ($fname ne '') { + my $content = &Apache::lonnet::getfile($item); + unless ($content eq '-1') { + my $storefn; + if (($key eq $oldurl) && (exists($docmoves{$key}))) { + $storefn = $docmoves{$key}; + } else { + $storefn = $relpath; + $storefn =~s{^/uploaded/$match_domain/$match_courseid/}{}; + if ($prefixchg && $before{'doc'} && $after{'doc'}) { + $storefn =~ s/^\Q$before{'doc'}\E/$after{'doc'}/; + } + if ($newsubdir{$key}) { + $storefn =~ s#^(docs|supplemental)/\Q$oldsubdir\E/#$1/$newsubdir{$key}/#; + } + } + ©_dependencies($item,$storefn,$relpath,$errors,\$content); + my $copyurl = + &Apache::lonclonecourse::writefile($env{'request.course.id'}, + $storefn.$fname,$content); + if ($copyurl eq '/adm/notfound.html') { + if (exists($docmoves{$oldurl})) { + return &mt('Paste failed: an error occurred copying the file.'); + } elsif (ref($errors) eq 'HASH') { + $errors->{$item} = 1; + } + } + } + } + } + } + } + foreach my $key (keys(%mapmoves)) { + my $storefn=$key; + $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{}; + if ($prefixchg && $before{'map'} && $after{'map'}) { + $storefn =~ s/^\Q$before{'map'}\E/$after{'map'}/; + } + if ($newsubdir{$key}) { + $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/; + } + my $mapcontent = &Apache::lonnet::getfile($key); + if ($mapcontent eq '-1') { + if (ref($errors) eq 'HASH') { + $errors->{$key} = 1; + } + } else { + my $newmap = + &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn, + $mapcontent); + if ($newmap eq '/adm/notfound.html') { + if (ref($errors) eq 'HASH') { + $errors->{$key} = 1; + } + } + } + } + my %updates; + if ($is_map) { + if (ref($updated) eq 'HASH') { + foreach my $type (keys(%{$updated})) { + if (ref($updated->{$type}) eq 'HASH') { + foreach my $key (keys(%{$updated->{$type}})) { + $updates{$key} = 1; + } + } + } + } + foreach my $key (keys(%updates)) { + my (%torewrite,%toretitle,%toremove,%remparam,%currparam,%zombie,%newdb); + if (ref($rewrites{$key}) eq 'HASH') { + %torewrite = %{$rewrites{$key}}; + } + if (ref($retitles{$key}) eq 'HASH') { + %toretitle = %{$retitles{$key}}; + } + if (ref($removefrommap{$key}) eq 'HASH') { + %toremove = %{$removefrommap{$key}}; + } + if (ref($removeparam{$key}) eq 'HASH') { + %remparam = %{$removeparam{$key}}; + } + if (ref($zombies{$key}) eq 'HASH') { + %zombie = %{$zombies{$key}}; + } + if (ref($dbcopies{$key}) eq 'HASH') { + foreach my $idx (keys(%{$dbcopies{$key}})) { + if (ref($dbcopies{$key}{$idx}) eq 'HASH') { + my ($newurl,$result,$errtext) = + &dbcopy($dbcopies{$key}{$idx},$cdom,$cnum,\%lockerrors); + if ($result eq 'ok') { + $newdb{$idx} = $newurl; + } elsif (ref($errors) eq 'HASH') { + $errors->{$key} = 1; + } + push(@msgs,$errtext); + } + } + } + if (ref($params{$key}) eq 'HASH') { + %currparam = %{$params{$key}}; + } + my ($errtext,$fatal) = &LONCAPA::map::mapread($key); + if ($fatal) { + return ($errtext); + } + for (my $i=0; $i<@LONCAPA::map::zombies; $i++) { + if (defined($LONCAPA::map::zombies[$i])) { + my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::zombies[$i]); + if ($zombie{$i} eq $src) { + undef($LONCAPA::map::zombies[$i]); + } + } + } + for (my $i=0; $i<@LONCAPA::map::order; $i++) { + my $idx = $LONCAPA::map::order[$i]; + if (defined($LONCAPA::map::resources[$idx])) { + my $changed; + my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::resources[$idx]); + if ((exists($toremove{$idx})) && + ($toremove{$idx} eq &LONCAPA::map::qtescape($src))) { + splice(@LONCAPA::map::order,$i,1); + if (ref($currparam{$idx}) eq 'ARRAY') { + foreach my $name (@{$currparam{$idx}}) { + &LONCAPA::map::delparameter($idx,'parameter_'.$name); + } + } + next; + } + my $origsrc = $src; + if ((exists($toretitle{$idx})) && ($toretitle{$idx} eq $src)) { + if ($title =~ m{^\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) { + $changed = 1; + } + } + if ((exists($torewrite{$idx})) && ($torewrite{$idx} eq $src)) { + $src =~ s{^/(uploaded|adm|public)/$match_domain/$match_courseid/}{/$1/$cdom/$cnum/}; + if ($origsrc =~ m{^/uploaded/}) { + if ($prefixchg && $before{'map'} && $after{'map'}) { + if ($src =~ /\.(page|sequence)$/) { + $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before{'map'}\E#$1$after{'map'}#; + } else { + $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before{'doc'}\E#$1$after{'doc'}#; + } + } + if ($origsrc =~ /\.(page|sequence)$/) { + if ($newsubdir{$origsrc}) { + $src =~ s#^(/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_)(\d+)#$1$newsubdir{$origsrc}#; + } + } elsif ($newsubdir{$key}) { + $src =~ s#^(/uploaded/$match_domain/$match_courseid/\w+/)(\d+)#$1$newsubdir{$key}#; + } + } + $changed = 1; + } elsif ($newdb{$idx} ne '') { + $src = $newdb{$idx}; + $changed = 1; + } + if ($changed) { + $LONCAPA::map::resources[$idx] = join(':',($title,&LONCAPA::map::qtunescape($src),$ext,$type)); + } + } + } + foreach my $idx (keys(%remparam)) { + if (ref($remparam{$idx}) eq 'ARRAY') { + foreach my $name (@{$remparam{$idx}}) { + &LONCAPA::map::delparameter($idx,'parameter_'.$name); + } + } + } + if (values(%lockerrors) > 0) { + $lockmsg = join('<br />',values(%lockerrors)); + } + my $storefn; + if ($key eq $oldurl) { + $storefn = $url; + $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{}; + } else { + $storefn = $key; + $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{}; + if ($prefixchg && $before{'map'} && $after{'map'}) { + $storefn =~ s/^\Q$before{'map'}\E/$after{'map'}/; + } + if ($newsubdir{$key}) { + $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/; + } + } + my $report; + if ($folder !~ /^supplemental/) { + $report = 1; + } + (my $outtext,$errtext) = + &LONCAPA::map::storemap("/uploaded/$cdom/$cnum/$storefn",1,$report); + if ($errtext) { + if ($caller eq 'paste') { + return (&mt('Paste failed: an error occurred saving the folder or page.')); + } + } + } + } + return ('ok',\@msgs,$lockmsg); +} + +sub copy_dependencies { + my ($item,$storefn,$relpath,$errors,$contentref) = @_; + my $content; + if (ref($contentref)) { + $content = $$contentref; + } else { + $content = &Apache::lonnet::getfile($item); + } + unless ($content eq '-1') { + my $mm = new File::MMagic; + my $mimetype = $mm->checktype_contents($content); + if ($mimetype eq 'text/html') { + my (%allfiles,%codebase,$state); + my $res = &Apache::lonnet::extract_embedded_items(undef,\%allfiles,\%codebase,\$content); + if ($res eq 'ok') { + my ($numexisting,$numpathchanges,$existing); + (undef,$numexisting,$numpathchanges,$existing) = + &Apache::loncommon::ask_for_embedded_content( + '/adm/coursedocs',$state,\%allfiles,\%codebase, + {'error_on_invalid_names' => 1, + 'ignore_remote_references' => 1, + 'docs_url' => $item, + 'context' => 'paste'}); + if ($numexisting > 0) { + if (ref($existing) eq 'HASH') { + foreach my $dep (keys(%{$existing})) { + my $depfile = $dep; + unless ($depfile =~ m{^\Q$relpath\E}) { + $depfile = $relpath.$dep; + } + my $depcontent = &Apache::lonnet::getfile($depfile); + unless ($depcontent eq '-1') { + my $storedep = $dep; + $storedep =~ s{^\Q$relpath\E}{}; + my $dep_url = + &Apache::lonclonecourse::writefile( + $env{'request.course.id'}, + $storefn.$storedep,$depcontent); + if ($dep_url eq '/adm/notfound.html') { + if (ref($errors) eq 'HASH') { + $errors->{$depfile} = 1; + } + } else { + ©_dependencies($depfile,$storefn,$relpath,$errors,\$depcontent); + } + } + } + } + } + } + } + } + return; +} + my %parameter_type = ( 'randompick' => 'int_pos', 'hiddenresource' => 'string_yesno', 'encrypturl' => 'string_yesno', @@ -1440,37 +2531,111 @@ my %parameter_type = ( 'randompick' my $valid_parameters_re = join('|',keys(%parameter_type)); # set parameters sub update_parameter { - - return 0 if ($env{'form.changeparms'} !~ /^($valid_parameters_re)$/); - - my $which = $env{'form.changeparms'}; - my $idx = $env{'form.setparms'}; - if ($env{'form.'.$which.'_'.$idx}) { - my $value = ($which eq 'randompick') ? $env{'form.'.$which.'_'.$idx} - : 'yes'; - &LONCAPA::map::storeparameter($idx, 'parameter_'.$which, $value, - $parameter_type{$which}); - &remember_parms($idx,$which,'set',$value); + if ($env{'form.changeparms'} eq 'all') { + my (@allidx,@allmapidx,%allchecked,%currchecked); + %allchecked = ( + 'hiddenresource' => {}, + 'encrypturl' => {}, + 'randompick' => {}, + 'randomorder' => {}, + ); + foreach my $which (keys(%allchecked)) { + $env{'form.all'.$which} =~ s/,$//; + if ($which eq 'randompick') { + foreach my $item (split(/,/,$env{'form.all'.$which})) { + my ($res,$value) = split(/:/,$item); + if ($value =~ /^\d+$/) { + $allchecked{$which}{$res} = $value; + } + } + } else { + if ($env{'form.all'.$which}) { + map { $allchecked{$which}{$_} = 1; } split(/,/,$env{'form.all'.$which}); + } + } + } + my $haschanges = 0; + foreach my $res (@LONCAPA::map::order) { + my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]); + $name=&LONCAPA::map::qtescape($name); + $url=&LONCAPA::map::qtescape($url); + next unless ($name && $url); + my $is_map; + if ($url =~ m{/uploaded/.+\.(page|sequence)$}) { + $is_map = 1; + } + foreach my $which (keys(%allchecked)) { + if (($which eq 'randompick' || $which eq 'randomorder')) { + next if (!$is_map); + } + my $oldvalue = 0; + my $newvalue = 0; + if ($allchecked{$which}{$res}) { + $newvalue = $allchecked{$which}{$res}; + } + my $current = (&LONCAPA::map::getparameter($res,'parameter_'.$which))[0]; + if ($which eq 'randompick') { + if ($current =~ /^(\d+)$/) { + $oldvalue = $1; + } + } else { + if ($current =~ /^yes$/i) { + $oldvalue = 1; + } + } + if ($oldvalue ne $newvalue) { + $haschanges = 1; + if ($newvalue) { + my $storeval = 'yes'; + if ($which eq 'randompick') { + $storeval = $newvalue; + } + &LONCAPA::map::storeparameter($res,'parameter_'.$which, + $storeval, + $parameter_type{$which}); + &remember_parms($res,$which,'set',$storeval); + } elsif ($oldvalue) { + &LONCAPA::map::delparameter($res,'parameter_'.$which); + &remember_parms($res,$which,'del'); + } + } + } + } + return $haschanges; } else { - &LONCAPA::map::delparameter($idx,'parameter_'.$which); + return 0 if ($env{'form.changeparms'} !~ /^($valid_parameters_re)$/); + + my $which = $env{'form.changeparms'}; + my $idx = $env{'form.setparms'}; + if ($env{'form.'.$which.'_'.$idx}) { + my $value = ($which eq 'randompick') ? $env{'form.rpicknum_'.$idx} + : 'yes'; + &LONCAPA::map::storeparameter($idx, 'parameter_'.$which, $value, + $parameter_type{$which}); + &remember_parms($idx,$which,'set',$value); + } else { + &LONCAPA::map::delparameter($idx,'parameter_'.$which); - &remember_parms($idx,$which,'del'); + &remember_parms($idx,$which,'del'); + } + return 1; } - return 1; } sub handle_edit_cmd { my ($coursenum,$coursedom) =@_; - + if ($env{'form.cmd'} eq '') { + return 0; + } my ($cmd,$idx)=split('_',$env{'form.cmd'}); my $ratstr = $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]; my ($title, $url, @rrest) = split(':', $ratstr); - if ($cmd eq 'del') { + if ($cmd eq 'remove') { if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) && - ($url!~/\.(page|sequence|problem|exam|quiz|assess|survey|form|library|task)$/)) { + ($url!~/$LONCAPA::assess_page_seq_re/)) { &Apache::lonnet::removeuploadedurl($url); } else { &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]); @@ -1490,7 +2655,6 @@ sub handle_edit_cmd { @LONCAPA::map::order[$idx+1,$idx] = @LONCAPA::map::order[$idx,$idx+1]; } elsif ($cmd eq 'rename') { - my $comment = &LONCAPA::map::qtunescape($env{'form.title'}); if ($comment=~/\S/) { $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]= @@ -1499,6 +2663,7 @@ sub handle_edit_cmd { # Devalidate title cache my $renamed_url=&LONCAPA::map::qtescape($url); &Apache::lonnet::devalidate_title_cache($renamed_url); + } else { return 0; } @@ -1506,9 +2671,29 @@ sub handle_edit_cmd { } sub editor { - my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output,$crstype)=@_; - my $container= ($env{'form.pagepath'}) ? 'page' - : 'sequence'; + my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output,$crstype, + $supplementalflag,$orderhash,$iconpath,$pathitem)=@_; + my ($randompick,$ishidden,$isencrypted,$plain,$is_random_order,$container); + if ($allowed) { + (my $breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain, + $is_random_order,$container) = + &Apache::lonhtmlcommon::docs_breadcrumbs($allowed,$crstype,1); + $r->print($breadcrumbtrail); + } elsif ($env{'form.folderpath'} =~ /\:1$/) { + $container = 'page'; + } else { + $container = 'sequence'; + } + + my $jumpto; + + unless ($supplementalflag) { + $jumpto = "uploaded/$coursedom/$coursenum/$folder.$container"; + } + + unless ($allowed) { + $randompick = -1; + } my ($errtext,$fatal) = &mapread($coursenum,$coursedom, $folder.'.'.$container); @@ -1521,15 +2706,6 @@ sub editor { $LONCAPA::map::resources[$idx]=''; } - my ($breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain,$is_random_order); - if ($allowed) { - ($breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain,$is_random_order) = - &breadcrumbs($allowed,$crstype); - $r->print($breadcrumbtrail); - } else { - $randompick = -1; - } - # ------------------------------------------------------------ Process commands # ---------------- if they are for this folder and user allowed to make changes @@ -1552,35 +2728,176 @@ sub editor { } if ($env{'form.pastemarked'}) { - my $paste_res = - &do_paste_from_buffer($coursenum,$coursedom,$folder); - if ($paste_res eq 'ok') { - ($errtext,$fatal) = &storemap($coursenum,$coursedom,$folder.'.'.$container); - return $errtext if ($fatal); - } elsif ($paste_res ne '') { - $r->print('<p><span class="LC_error">'.$paste_res.'</span></p>'); + my %paste_errors; + my ($paste_res,$save_error,$pastemsgarray,$lockerror) = + &do_paste_from_buffer($coursenum,$coursedom,$folder,$container, + \%paste_errors); + if (ref($pastemsgarray) eq 'ARRAY') { + if (@{$pastemsgarray} > 0) { + $r->print('<p class="LC_info">'. + join('<br />',@{$pastemsgarray}). + '</p>'); + } } - } + if ($lockerror) { + $r->print('<p class="LC_error">'. + $lockerror. + '</p>'); + } + if ($save_error ne '') { + return $save_error; + } + if ($paste_res) { + my %errortext = &Apache::lonlocal::texthash ( + fail => 'Storage of folder contents failed', + failread => 'Reading folder contents failed', + failstore => 'Storage of folder contents failed', + ); + if ($errortext{$paste_res}) { + $r->print('<p class="LC_error">'.$errortext{$paste_res}.'</p>'); + } + } + if (keys(%paste_errors) > 0) { + $r->print('<p class="LC_warning">'."\n". + &mt('The following files are either dependencies of a web page or references within a folder and/or composite page which could not be copied during the paste operation:')."\n". + '<ul>'."\n"); + foreach my $key (sort(keys(%paste_errors))) { + $r->print('<li>'.$key.'</li>'."\n"); + } + $r->print('</ul></p>'."\n"); + } + } elsif ($env{'form.clearmarked'}) { + my $output = &do_buffer_empty(); + if ($output) { + $r->print('<p class="LC_info">'.$output.'</p>'); + } + } $r->print($upload_output); +# Rename, cut, copy or remove a single resource if (&handle_edit_cmd()) { - ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container); + my $contentchg; + if ($env{'form.cmd'} =~ m{^(del|cut)_}) { + $contentchg = 1; + } + ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container,$contentchg); return $errtext if ($fatal); } + +# Cut, copy and/or remove multiple resources + if ($env{'form.multichange'}) { + my %allchecked = ( + cut => {}, + remove => {}, + ); + my $needsupdate; + foreach my $which (keys(%allchecked)) { + $env{'form.multi'.$which} =~ s/,$//; + if ($env{'form.multi'.$which}) { + map { $allchecked{$which}{$_} = 1; } split(/,/,$env{'form.multi'.$which}); + if (ref($allchecked{$which}) eq 'HASH') { + $needsupdate += scalar(keys(%{$allchecked{$which}})); + } + } + } + if ($needsupdate) { + my $haschanges = 0; + my %curr_groups = &Apache::longroup::coursegroups(); + my $total = scalar(@LONCAPA::map::order) - 1; + for (my $i=$total; $i>=0; $i--) { + my $res = $LONCAPA::map::order[$i]; + my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]); + $name=&LONCAPA::map::qtescape($name); + $url=&LONCAPA::map::qtescape($url); + next unless ($name && $url); + my %denied = + &action_restrictions($coursenum,$coursedom,$url, + $env{'form.folderpath'},\%curr_groups); + foreach my $which (keys(%allchecked)) { + next if ($denied{$which}); + next unless ($allchecked{$which}{$res}); + if ($which eq 'remove') { + if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) && + ($url!~/$LONCAPA::assess_page_seq_re/)) { + &Apache::lonnet::removeuploadedurl($url); + } else { + &LONCAPA::map::makezombie($res); + } + splice(@LONCAPA::map::order,$i,1); + $haschanges ++; + } elsif ($which eq 'cut') { + &LONCAPA::map::makezombie($res); + splice(@LONCAPA::map::order,$i,1); + $haschanges ++; + } + } + } + if ($haschanges) { + ($errtext,$fatal) = + &storemap($coursenum,$coursedom,$folder.'.'.$container,1); + return $errtext if ($fatal); + } + } + } + # Group import/search if ($env{'form.importdetail'}) { my @imports; foreach my $item (split(/\&/,$env{'form.importdetail'})) { if (defined($item)) { my ($name,$url,$residx)= - map {&unescape($_)} split(/\=/,$item); + map { &unescape($_); } split(/\=/,$item); + if ($url =~ m{^\Q/uploaded/$coursedom/$coursenum/\E(default|supplemental)_new\.(sequence|page)$}) { + my ($suffix,$errortxt,$locknotfreed) = + &new_timebased_suffix($coursedom,$coursenum,'map',$1,$2); + if ($locknotfreed) { + $r->print($locknotfreed); + } + if ($suffix) { + $url =~ s/_new\./_$suffix./; + } else { + return $errortxt; + } + } elsif ($url =~ m{^/adm/$match_domain/$match_username/new/(smppg|bulletinboard)$}) { + my $type = $1; + my ($suffix,$errortxt,$locknotfreed) = + &new_timebased_suffix($coursedom,$coursenum,$type); + if ($locknotfreed) { + $r->print($locknotfreed); + } + if ($suffix) { + $url =~ s{^(/adm/$match_domain/$match_username)/new}{$1/$suffix}; + } else { + return $errortxt; + } + } elsif ($url =~ m{^/uploaded/$coursedom/$coursenum/(docs|supplemental)/(default|\d+)/new.html$}) { + if ($supplementalflag) { + next unless ($1 eq 'supplemental'); + if ($folder eq 'supplemental') { + next unless ($2 eq 'default'); + } else { + next unless ($folder eq 'supplemental_'.$2); + } + } else { + next unless ($1 eq 'docs'); + if ($folder eq 'default') { + next unless ($2 eq 'default'); + } else { + next unless ($folder eq 'default_'.$2); + } + } + } push(@imports, [$name, $url, $residx]); } } - ($errtext,$fatal)=&group_import($coursenum, $coursedom, $folder, - $container,'londocs',@imports); + ($errtext,$fatal,my $fixuperrors) = + &group_import($coursenum, $coursedom, $folder,$container, + 'londocs',@imports); return $errtext if ($fatal); + if ($fixuperrors) { + $r->print($fixuperrors); + } } # Loading a complete map if ($env{'form.loadmap'}) { @@ -1592,7 +2909,7 @@ sub editor { $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx; } ($errtext,$fatal)=&storemap($coursenum,$coursedom, - $folder.'.'.$container); + $folder.'.'.$container,1); return $errtext if ($fatal); } else { $r->print('<p><span class="LC_error">'.&mt('No map selected.').'</span></p>'); @@ -1636,8 +2953,17 @@ sub editor { $r->print('</div>'); } - my $output; - + my ($to_show,$output,@allidx,@allmapidx,%filters,%lists,%curr_groups); + %filters = ( + canremove => [], + cancut => [], + cancopy => [], + hiddenresource => [], + encrypturl => [], + randomorder => [], + randompick => [], + ); + %curr_groups = &Apache::longroup::coursegroups(); &Apache::loncommon::start_data_table_count(); #setup a row counter foreach my $res (@LONCAPA::map::order) { my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]); @@ -1645,43 +2971,222 @@ sub editor { $url=&LONCAPA::map::qtescape($url); unless ($name) { $name=(split(/\//,$url))[-1]; } unless ($name) { $idx++; next; } + push(@allidx,$res); + if ($url =~ m{/uploaded/.+\.(page|sequence)$}) { + push(@allmapidx,$res); + } $output .= &entryline($idx,$name,$url,$folder,$allowed,$res, - $coursenum,$crstype); + $coursenum,$coursedom,$crstype, + $pathitem,$supplementalflag,$container, + \%filters,\%curr_groups); $idx++; $shown++; } &Apache::loncommon::end_data_table_count(); - - if ($shown) { - $r->print(&Apache::loncommon::start_data_table()); - if ($allowed) { - $r->print(&Apache::loncommon::start_data_table_header_row() - .'<th colspan="2">'.&mt('Move').'</th>' - .'<th>'.&mt('Actions').'</th>' - .'<th colspan="2">'.&mt('Document').'</th>'); - if ($folder !~ /^supplemental/) { - $->print('<th colspan="4">'.&mt('Settings').'</th>'); + + my $need_save; + if (($allowed) || ($supplementalflag && $folder eq 'supplemental')) { + my $toolslink; + if ($allowed || &Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { + $toolslink = '<table><tr><td>' + .&Apache::loncommon::help_open_menu('Navigation Screen', + 'Navigation_Screen',undef,'RAT') + .'</td><td class="LC_middle">'.&mt('Tools:').'</td>' + .'<td align="left"><ul id="LC_toolbar">' + .'<li><a href="/adm/coursedocs?forcesupplement=1&command=editsupp" ' + .'id="LC_content_toolbar_edittoplevel" ' + .'class="LC_toolbarItem" ' + .'title="'.&mt('Supplemental Content Editor').'">' + .'</a></li></ul></td></tr></table><br />'; + } + if ($shown) { + if ($allowed) { + $to_show = &Apache::loncommon::start_scrollbox('900px','880px','400px','contentscroll') + .&Apache::loncommon::start_data_table(undef,'contentlist') + .&Apache::loncommon::start_data_table_header_row() + .'<th colspan="2">'.&mt('Move').'</th>' + .'<th colspan="2">'.&mt('Actions').'</th>' + .'<th>'.&mt('Document').'</th>'; + if ($folder !~ /^supplemental/) { + $to_show .= '<th colspan="4">'.&mt('Settings').'</th>'; + } + $to_show .= &Apache::loncommon::end_data_table_header_row(); + if ($folder !~ /^supplemental/) { + $lists{'canhide'} = join(',',@allidx); + $lists{'canrandomlyorder'} = join(',',@allmapidx); + my @possfilters = ('canremove','cancut','cancopy','hiddenresource','encrypturl', + 'randomorder','randompick'); + foreach my $item (@possfilters) { + if (ref($filters{$item}) eq 'ARRAY') { + if (@{$filters{$item}} > 0) { + $lists{$item} = join(',',@{$filters{$item}}); + } + } + } + if (@allidx > 0) { + my $path; + if ($env{'form.folderpath'}) { + $path = + &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); + } + if (@allidx > 1) { + $to_show .= + &Apache::loncommon::continue_data_table_row(). + '<td colspan="2"> </td>'. + '<td>'. + &multiple_check_form('actions',\%lists). + '</td>'. + '<td> </td>'. + '<td> </td>'. + '<td colspan="4">'. + &multiple_check_form('settings',\%lists). + '</td>'. + &Apache::loncommon::end_data_table_row(); + $need_save = 1; + } + } + } + $to_show .= $output.' ' + .&Apache::loncommon::end_data_table() + .'<br style="line-height:2px;" />' + .&Apache::loncommon::end_scrollbox(); + } else { + $to_show .= $toolslink + .&Apache::loncommon::start_data_table('LC_tableOfContent') + .$output.' ' + .&Apache::loncommon::end_data_table(); + } + } else { + if (!$allowed) { + $to_show .= $toolslink; } - $r->print(&Apache::loncommon::end_data_table_header_row()); + $to_show .= &Apache::loncommon::start_scrollbox('400px','380px','200px','contentscroll') + .'<div class="LC_info" id="contentlist">' + .&mt('Currently empty') + .'</div>' + .&Apache::loncommon::end_scrollbox(); } - $r->print($output - .&Apache::loncommon::end_data_table() - ); } else { - $r->print('<p class="LC_info">' - .&mt('Currently no documents.') - .'</p>' - ); + if ($shown) { + $to_show = '<div>' + .&Apache::loncommon::start_data_table('LC_tableOfContent') + .$output + .&Apache::loncommon::end_data_table() + .'</div>'; + } else { + $to_show = '<div class="LC_info" id="contentlist">' + .&mt('Currently empty') + .'</div>' + } + } + my $tid = 1; + if ($supplementalflag) { + $tid = 2; } if ($allowed) { - &print_paste_buffer($r,$container); + my $readfile="/uploaded/$coursedom/$coursenum/$folder.$container"; + $r->print(&generate_edit_table($tid,$orderhash,$to_show,$iconpath, + $jumpto,$readfile,$need_save,"$folder.$container")); + &print_paste_buffer($r,$container,$folder,$coursedom,$coursenum); + } else { + $r->print($to_show); } return; } +sub multiple_check_form { + my ($caller,$listsref) = @_; + return unless (ref($listsref) eq 'HASH'); + my $output = + '<form action="/adm/coursedocs" method="post" name="togglemult'.$caller.'">'. + '<span class="LC_nobreak" style="font-size:x-small;font-weight:bold;">'. + '<label><input type="radio" name="showmultpick" value="0" onclick="javascript:togglePick('."'$caller','0'".');" checked="checked" />'.&mt('one').'</label>'.(' 'x2).'<label><input type="radio" name="showmultpick" value="1" onclick="javascript:togglePick('."'$caller','1'".');" />'.&mt('multiple').'</label></span><span id="more'.$caller.'" class="LC_nobreak LC_docs_ext_edit"></span></form>'. + '<div id="multi'.$caller.'" style="display:none;margin:0;padding:0;border:0">'. + '<form action="/adm/coursedocs" method="post" name="cumulative'.$caller.'">'."\n". + '<fieldset id="allfields'.$caller.'" style="display:none"><legend style="font-size:x-small;">'.&mt('check/uncheck all').'</legend>'."\n"; + if ($caller eq 'settings') { + $output .= + '<table><tr>'. + '<td class="LC_docs_entry_parameter">'. + '<span class="LC_nobreak"><label>'. + '<input type="checkbox" name="hiddenresourceall" id="hiddenresourceall" onclick="propagateState(this.form,'."'hiddenresource'".')" />'.&mt('Hidden'). + '</label></span></td>'. + '<td class="LC_docs_entry_parameter">'. + '<span class="LC_nobreak"><label><input type="checkbox" name="randompickall" id="randompickall" onclick="updatePick(this.form,'."'all','check'".');propagateState(this.form,'."'randompick'".');propagateState(this.form,'."'rpicknum'".');" />'.&mt('Randomly Pick').'</label><span id="rpicktextall"></span><input type="hidden" name="rpicknumall" id="rpicknumall" value="" />'. + '</span></td>'. + '</tr>'."\n". + '<tr>'. + '<td class="LC_docs_entry_parameter">'. + '<span class="LC_nobreak"><label><input type="checkbox" name="encrypturlall" id="encrypturlall" onclick="propagateState(this.form,'."'encrypturl'".')" />'.&mt('URL hidden').'</label></span></td><td class="LC_docs_entry_parameter"><span class="LC_nobreak"><label><input type="checkbox" name="randomorderall" id="randomorderall" onclick="propagateState(this.form,'."'randomorder'".')" />'.&mt('Random Order'). + '</label></span>'. + '</td></tr></table>'."\n"; + } else { + $output .= + '<table><tr>'. + '<td class="LC_docs_entry_parameter">'. + '<span class="LC_nobreak LC_docs_remove">'. + '<label><input type="checkbox" name="removeall" id="removeall" onclick="propagateState(this.form,'."'remove'".')" />'.&mt('Remove'). + '</label></span></td>'. + '<td class="LC_docs_entry_parameter">'. + '<span class="LC_nobreak LC_docs_cut">'. + '<label><input type="checkbox" name="cut" id="cutall" onclick="propagateState(this.form,'."'cut'".');" />'.&mt('Cut'). + '</label></span></td>'."\n". + '<td class="LC_docs_entry_parameter">'. + '<span class="LC_nobreak LC_docs_copy">'. + '<label><input type="checkbox" name="copyall" id="copyall" onclick="propagateState(this.form,'."'copy'".')" />'.&mt('Copy'). + '</label></span></td>'. + '</tr></table>'."\n"; + } + $output .= + '</fieldset>'. + '<input type="hidden" name="allidx" value="'.$listsref->{'canhide'}.'" />'; + if ($caller eq 'settings') { + $output .= + '<input type="hidden" name="allmapidx" value="'.$listsref->{'canrandomlyorder'}.'" />'."\n". + '<input type="hidden" name="currhiddenresource" value="'.$listsref->{'hiddenresource'}.'" />'."\n". + '<input type="hidden" name="currencrypturl" value="'.$listsref->{'encrypturl'}.'" />'."\n". + '<input type="hidden" name="currrandomorder" value="'.$listsref->{'randomorder'}.'" />'."\n". + '<input type="hidden" name="currrandompick" value="'.$listsref->{'randompick'}.'" />'."\n"; + } elsif ($caller eq 'actions') { + $output .= + '<input type="hidden" name="allremoveidx" id="allremoveidx" value="'.$listsref->{'canremove'}.'" />'. + '<input type="hidden" name="allcutidx" id="allcutidx" value="'.$listsref->{'cancut'}.'" />'. + '<input type="hidden" name="allcopyidx" id="allcopyidx" value="'.$listsref->{'cancopy'}.'" />'; + } + $output .= + '</form>'. + '</div>'; + return $output; +} + sub process_file_upload { - my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd) = @_; + my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd,$crstype) = @_; # upload a file, if present + my $filesize = length($env{'form.uploaddoc'}); + if (!$filesize) { + $$upload_output = '<div class="LC_error">'. + &mt('Unable to upload [_1]. (size = [_2] bytes)', + '<span class="LC_filename">'.$env{'form.uploaddoc.filename'}.'</span>', + $filesize).'<br />'. + &mt('Either the file you attempted to upload was empty, or your web browser was unable to read its contents.').'<br />'. + '</div>'; + return; + } + my $quotatype = 'unofficial'; + if ($crstype eq 'Community') { + $quotatype = 'community'; + } elsif ($env{'course.'.$coursedom.'_'.$coursenum.'.internal.coursecode'}) { + $quotatype = 'official'; + } elsif ($env{'course.'.$coursedom.'_'.$coursenum.'.internal.textbook'}) { + $quotatype = 'textbook'; + } + if (&Apache::loncommon::get_user_quota($coursenum,$coursedom,'course',$quotatype)) { + $filesize = int($filesize/1000); #expressed in kb + $$upload_output = &Apache::loncommon::excess_filesize_warning($coursenum,$coursedom,'course', + $env{'form.uploaddoc.filename'},$filesize, + 'upload',$quotatype); + return if ($$upload_output); + } my ($parseaction,$showupload,$nextphase,$mimetype); if ($env{'form.parserflag'}) { $parseaction = 'parse'; @@ -1694,19 +3199,15 @@ sub process_file_upload { my $errtext=''; my $fatal=0; my $container='sequence'; - if ($env{'form.pagepath'}) { + if ($env{'form.folderpath'} =~ /:1$/) { $container='page'; } ($errtext,$fatal)= - &mapread($coursenum,$coursedom,$folder.'.'.$container); + &mapread($coursenum,$coursedom,$folder.'.'.$container); if ($#LONCAPA::map::order<1) { $LONCAPA::map::order[0]=1; $LONCAPA::map::resources[1]=''; } - if ($fatal) { - $$upload_output = '<p><span class="LC_error">'.&mt('The uploaded file has not been stored as an error occurred reading the contents of the current folder.').'</span></p>'; - return; - } my $destination = 'docs/'; if ($folder =~ /^supplemental/) { $destination = 'supplemental/'; @@ -1716,6 +3217,10 @@ sub process_file_upload { } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) { $destination .= $2.'/'; } + if ($fatal) { + $$upload_output = '<div class="LC_error" id="uploadfileresult">'.&mt('The uploaded file has not been stored as an error occurred reading the contents of the current folder.').'</div>'; + return; + } # this is for a course, not a user, so set context to coursedoc. my $newidx=&LONCAPA::map::getresidx(); $destination .= $newidx; @@ -1730,7 +3235,7 @@ sub process_file_upload { } else { my ($filename) = ($env{'form.uploaddoc.filename'} =~ m{([^/]+)$}); - $$upload_output = '<p><span class="LC_error">'.&mt('Unable to save file [_1].','<span class="LC_filename">'.$filename.'</span>').'</span></p>'; + $$upload_output = '<div class="LC_error" id="uploadfileresult">'.&mt('Unable to save file [_1].','<span class="LC_filename">'.$filename.'</span>').'</div>'; return; } my $ext='false'; @@ -1747,9 +3252,9 @@ sub process_file_upload { $comment.':'.$url.':'.$ext.':normal:res'; $LONCAPA::map::order[$#LONCAPA::map::order+1]= $newidx; ($errtext,$fatal)=&storemap($coursenum,$coursedom, - $folder.'.'.$container); + $folder.'.'.$container,1); if ($fatal) { - $$upload_output = '<p><span class="LC_error">'.$errtext.'</span></p>'; + $$upload_output = '<div class="LC_error" id="uploadfileresult">'.$errtext.'</div>'; return; } else { if ($parseaction eq 'parse' && $mimetype eq 'text/html') { @@ -1776,84 +3281,133 @@ sub process_file_upload { } else { $$upload_output .= &mt('No embedded items identified').'<br />'; } + $$upload_output = '<div id="uploadfileresult">'.$$upload_output.'</div>'; + } elsif ((&Apache::loncommon::is_archive_file($mimetype)) && + ($env{'form.uploaddoc.filename'} =~ /\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/i)) { + $nextphase = 'decompress_uploaded'; + my $position = scalar(@LONCAPA::map::order)-1; + my $noextract = &return_to_editor(); + my $archiveurl = &HTML::Entities::encode($url,'<>&"'); + my %archiveitems = ( + folderpath => $env{'form.folderpath'}, + cmd => $nextphase, + newidx => $newidx, + position => $position, + phase => $nextphase, + comment => $comment, + ); + my ($destination,$dir_root) = &embedded_destination($coursenum,$coursedom); + my @current = &get_dir_list($url,$coursenum,$coursedom,$newidx); + $$upload_output = $showupload. + &Apache::loncommon::decompress_form($mimetype, + $archiveurl,'/adm/coursedocs',$noextract, + \%archiveitems,\@current); } } } return $nextphase; } -sub is_supplemental_title { - my ($title) = @_; - return scalar($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/); +sub get_dir_list { + my ($url,$coursenum,$coursedom,$newidx) = @_; + my ($destination,$dir_root) = &embedded_destination(); + my ($dirlistref,$listerror) = + &Apache::lonnet::dirlist("$dir_root/$destination/$newidx",$coursedom,$coursenum,1); + my @dir_lines; + my $dirptr=16384; + if (ref($dirlistref) eq 'ARRAY') { + foreach my $dir_line (sort + { + my ($afile)=split('&',$a,2); + my ($bfile)=split('&',$b,2); + return (lc($afile) cmp lc($bfile)); + } (@{$dirlistref})) { + my ($filename,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef)=split(/\&/,$dir_line,16); + $filename =~ s/\s+$//; + next if ($filename =~ /^\.\.?$/); + my $isdir = 0; + if ($dirptr&$testdir) { + $isdir = 1; + } + push(@dir_lines, [$filename,$dom,$isdir,$size,$mtime,$obs]); + } + } + return @dir_lines; } -sub parse_supplemental_title { +sub is_supplemental_title { my ($title) = @_; - - my ($foldertitle,$renametitle); - if ($title =~ /&&&/) { - $title = &HTML::Entites::decode($title); - } - if ($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/) { - $renametitle=$4; - my ($time,$uname,$udom) = ($1,$2,$3); - $foldertitle=&Apache::lontexconvert::msgtexconverted($4); - my $name = &Apache::loncommon::plainname($uname,$udom); - $name = &HTML::Entities::encode($name,'"<>&\''); - $renametitle = &HTML::Entities::encode($renametitle,'"<>&\''); - $title='<i>'.&Apache::lonlocal::locallocaltime($time).'</i> '. - $name.': <br />'.$foldertitle; - } - if (wantarray) { - return ($title,$foldertitle,$renametitle); - } - return $title; + return scalar($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/); } # --------------------------------------------------------------- An entry line sub entryline { - my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$crstype)=@_; - my ($foldertitle,$pagetitle,$renametitle); + my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$coursedom, + $crstype,$pathitem,$supplementalflag,$container,$filtersref,$currgroups)=@_; + my ($foldertitle,$renametitle,$oldtitle); if (&is_supplemental_title($title)) { - ($title,$foldertitle,$renametitle) = &parse_supplemental_title($title); - $pagetitle = $foldertitle; + ($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title); } else { $title=&HTML::Entities::encode($title,'"<>&\''); $renametitle=$title; $foldertitle=$title; - $pagetitle=$title; } my $orderidx=$LONCAPA::map::order[$index]; - $renametitle=~s/\\/\\\\/g; $renametitle=~s/\"\;/\\\"/g; $renametitle=~s/ /%20/g; + $oldtitle = $renametitle; + $renametitle=~s/\'/\\\'/g; my $line=&Apache::loncommon::start_data_table_row(); - my ($form_start,$form_end); + my ($form_start,$form_end,$form_common,$form_param); # Edit commands - my ($container, $type, $esc_path, $path, $symb); + my ($esc_path, $path, $symb); if ($env{'form.folderpath'}) { - $type = 'folder'; - $container = 'sequence'; $esc_path=&escape($env{'form.folderpath'}); $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); # $htmlfoldername=&HTML::Entities::encode($env{'form.foldername'},'<>&"'); } - if ($env{'form.pagepath'}) { - $type = $container = 'page'; - $esc_path=&escape($env{'form.pagepath'}); - $path = &HTML::Entities::encode($env{'form.pagepath'},'<>&"'); - $symb=&escape($env{'form.pagesymb'}); + my $isexternal; + if ($residx) { + my $currurl = $url; + $currurl =~ s{^http(|s)(:|:)//}{/adm/wrapper/ext/}; + if ($currurl =~ m{^/adm/wrapper/ext/}) { + $isexternal = 1; + } + if (!$supplementalflag) { + my $path = 'uploaded/'. + $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'. + $env{'course.'.$env{'request.course.id'}.'.num'}.'/'; + $symb = &Apache::lonnet::encode_symb($path.$folder.".$container", + $residx, + &Apache::lonnet::declutter($currurl)); + } + } + my ($renamelink,%lt,$ishash); + if (ref($filtersref) eq 'HASH') { + $ishash = 1; } - my $cpinfo=''; + if ($allowed) { + $form_start = ' + <form action="/adm/coursedocs" method="post"> +'; + $form_common=(<<END); + <input type="hidden" name="folderpath" value="$path" /> + <input type="hidden" name="symb" value="$symb" /> +END + $form_param=(<<END); + <input type="hidden" name="setparms" value="$orderidx" /> + <input type="hidden" name="changeparms" value="0" /> +END + $form_end = '</form>'; + my $incindex=$index+1; my $selectbox=''; - if (($folder!~/^supplemental/) && - ($#LONCAPA::map::order>0) && + if (($#LONCAPA::map::order>0) && ((split(/\:/, $LONCAPA::map::resources[$LONCAPA::map::order[0]]))[1] ne '') && @@ -1872,36 +3426,24 @@ sub entryline { } $selectbox.='</select>'; } - my %lt=&Apache::lonlocal::texthash( + %lt=&Apache::lonlocal::texthash( 'up' => 'Move Up', 'dw' => 'Move Down', 'rm' => 'Remove', 'ct' => 'Cut', 'rn' => 'Rename', - 'cp' => 'Copy'); - my $nocopy=0; - my $nocut=0; - if ($url=~/\.(page|sequence)$/) { - if ($url =~ m{/res/}) { - # no copy for published maps - $nocopy = 1; - } else { - foreach my $item (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$url),1)) { - my ($title,$url,$ext,$type)=split(/\:/,$item); - if (($url=~/\.(page|sequence)/) && ($type ne 'zombie')) { - $nocopy=1; - last; - } - } - } - } - if ($url=~/^\/res\/lib\/templates\//) { - $nocopy=1; - $nocut=1; - } - my $copylink=' '; - my $cutlink=' '; - + 'cp' => 'Copy', + 'ex' => 'External Resource', + 'ed' => 'Edit', + 'pr' => 'Preview', + 'sv' => 'Save', + 'ul' => 'URL', + 'ti' => 'Title', + ); + my %denied = &action_restrictions($coursenum,$coursedom,$url, + $env{'form.folderpath'}, + $currgroups); + my ($copylink,$cutlink,$removelink); my $skip_confirm = 0; if ( $folder =~ /^supplemental/ || ($url =~ m{( /smppg$ @@ -1909,213 +3451,433 @@ sub entryline { |/aboutme$ |/navmaps$ |/bulletinboard$ - |\.html$ - |^/adm/wrapper/ext)}x)) { + |\.html$)}x) + || $isexternal) { $skip_confirm = 1; } - if (!$nocopy) { + if ($denied{'copy'}) { + $copylink=(<<ENDCOPY) +<span style="visibility: hidden;">$lt{'cp'}</span> +ENDCOPY + } else { + my $formname = 'edit_copy_'.$orderidx; + my $js = "javascript:checkForSubmit(document.forms.renameform,'copy','actions','$orderidx','$esc_path','$index','$renametitle',$skip_confirm,'$container','$folder');"; $copylink=(<<ENDCOPY); -<a href='javascript:markcopy("$esc_path","$index","$renametitle","$container","$symb","$folder");' class="LC_docs_copy">$lt{'cp'}</a> +<form name="$formname" method="post" action="/adm/coursedocs"> +$form_common +<input type="checkbox" name="copy" id="copy_$orderidx" value="$orderidx" onclick="javascript:singleCheck(this,'$orderidx','copy');" class="LC_hidden" /><a href="$js" class="LC_docs_copy">$lt{'cp'}</a> +$form_end ENDCOPY + if (($ishash) && (ref($filtersref->{'cancopy'}) eq 'ARRAY')) { + push(@{$filtersref->{'cancopy'}},$orderidx); + } } - if (!$nocut) { + if ($denied{'cut'}) { + $cutlink=(<<ENDCUT); +<span style="visibility: hidden;">$lt{'ct'}</span> +ENDCUT + } else { + my $formname = 'edit_cut_'.$orderidx; + my $js = "javascript:checkForSubmit(document.forms.renameform,'cut','actions','$orderidx','$esc_path','$index','$renametitle',$skip_confirm,'$container','$folder');"; $cutlink=(<<ENDCUT); -<a href='javascript:cutres("$esc_path","$index","$renametitle","$container","$symb","$folder",$skip_confirm);' class="LC_docs_cut">$lt{'ct'}</a> +<form name="$formname" method="post" action="/adm/coursedocs"> +$form_common +<input type="hidden" name="skip_$orderidx" id="skip_cut_$orderidx" value="$skip_confirm" /> +<input type="checkbox" name="cut" id="cut_$orderidx" value="$orderidx" onclick="javascript:singleCheck(this,'$orderidx','cut');" class="LC_hidden" /><a href="$js" class="LC_docs_cut">$lt{'ct'}</a> +$form_end ENDCUT + if (($ishash) && (ref($filtersref->{'cancut'}) eq 'ARRAY')) { + push(@{$filtersref->{'cancut'}},$orderidx); + } } - $form_start = (<<END); - <form action="/adm/coursedocs" method="post"> - <input type="hidden" name="${type}path" value="$path" /> - <input type="hidden" name="${type}symb" value="$symb" /> - <input type="hidden" name="setparms" value="$orderidx" /> - <input type="hidden" name="changeparms" value="0" /> -END - $form_end = '</form>'; + if ($denied{'remove'}) { + $removelink=(<<ENDREM); +<span style="visibility: hidden;">$lt{'rm'}</a> +ENDREM + } else { + my $formname = 'edit_remove_'.$orderidx; + my $js = "javascript:checkForSubmit(document.forms.renameform,'remove','actions','$orderidx','$esc_path','$index','$renametitle',$skip_confirm);"; + $removelink=(<<ENDREM); +<form name="$formname" method="post" action="/adm/coursedocs"> +$form_common +<input type="hidden" name="skip_$orderidx" id="skip_remove_$orderidx" value="$skip_confirm" /> +<input type="checkbox" name="remove" id="remove_$orderidx" value="$orderidx" onclick="javascript:singleCheck(this,'$orderidx','remove');" class="LC_hidden" /><a href="$js" class="LC_docs_remove">$lt{'rm'}</a> +$form_end +ENDREM + if (($ishash) && (ref($filtersref->{'canremove'}) eq 'ARRAY')) { + push(@{$filtersref->{'canremove'}},$orderidx); + } + } + $renamelink=(<<ENDREN); +<a href='javascript:changename("$esc_path","$index","$oldtitle");' class="LC_docs_rename">$lt{'rn'}</a> +ENDREN $line.=(<<END); <td> <div class="LC_docs_entry_move"> - <a href='/adm/coursedocs?cmd=up_$index&${type}path=$esc_path&${type}symb=$symb$cpinfo'> - <img src="${iconpath}move_up.gif" alt='$lt{'up'}' class="LC_icon" /> + <a href='/adm/coursedocs?cmd=up_$index&folderpath=$esc_path&symb=$symb'> + <img src="${iconpath}move_up.gif" alt="$lt{'up'}" class="LC_icon" /> </a> </div> <div class="LC_docs_entry_move"> - <a href='/adm/coursedocs?cmd=down_$index&${type}path=$esc_path&${type}symb=$symb$cpinfo'> - <img src="${iconpath}move_down.gif" alt='$lt{'dw'}' class="LC_icon" /> + <a href='/adm/coursedocs?cmd=down_$index&folderpath=$esc_path&symb=$symb'> + <img src="${iconpath}move_down.gif" alt="$lt{'dw'}" class="LC_icon" /> </a> </div> </td> <td> $form_start + $form_param + $form_common $selectbox $form_end </td> -<td class="LC_docs_entry_commands"> - <a href='javascript:removeres("$esc_path","$index","$renametitle","$container","$symb",$skip_confirm);' class="LC_docs_remove">$lt{'rm'}</a> +<td class="LC_docs_entry_commands LC_nobreak"> +$removelink $cutlink - <a href='javascript:changename("$esc_path","$index","$renametitle","$container","$symb");' class="LC_docs_rename">$lt{'rn'}</a> $copylink </td> END - } # Figure out what kind of a resource this is my ($extension)=($url=~/\.(\w+)$/); my $uploaded=($url=~/^\/*uploaded\//); my $icon=&Apache::loncommon::icon($url); - my $isfolder=0; - my $ispage=0; - my $folderarg; - my $pagearg; - my $pagefile; + my $isfolder; + my $ispage; + my $containerarg; if ($uploaded) { - if ($extension eq 'sequence') { - $icon=$iconpath.'/navmap.folder.closed.gif'; - $url=~/\Q$coursenum\E\/([\/\w]+)\.sequence$/; - $url='/adm/coursedocs?'; - $folderarg=$1; - $isfolder=1; - } elsif ($extension eq 'page') { - $icon=$iconpath.'/page.gif'; - $url=~/\Q$coursenum\E\/([\/\w]+)\.page$/; - $pagearg=$1; - $url='/adm/coursedocs?'; - $ispage=1; + if (($extension eq 'sequence') || ($extension eq 'page')) { + $url=~/\Q$coursenum\E\/([\/\w]+)\.\Q$extension\E$/; + $containerarg = $1; + if ($extension eq 'sequence') { + $icon=$iconpath.'navmap.folder.closed.gif'; + $isfolder=1; + } else { + $icon=$iconpath.'page.gif'; + $ispage=1; + } + if ($allowed) { + $url='/adm/coursedocs?'; + } else { + $url='/adm/supplemental?'; + } } else { &Apache::lonnet::allowuploaded('/adm/coursedoc',$url); } } + my ($editlink,$extresform); my $orig_url = $url; $orig_url=~s{http(:|:)//https(:|:)//}{https$2//}; - my $external = ($url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/}); - if ((!$isfolder) && ($residx) && ($folder!~/supplemental/) && (!$ispage)) { - my $symb=&Apache::lonnet::symbclean( - &Apache::lonnet::declutter('uploaded/'. - $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'. - $env{'course.'.$env{'request.course.id'}.'.num'}.'/'.$folder. - '.sequence'). - '___'.$residx.'___'. - &Apache::lonnet::declutter($url)); - (undef,undef,$url)=&Apache::lonnet::decode_symb($symb); - $url=&Apache::lonnet::clutter($url); - if ($url=~/^\/*uploaded\//) { - $url=~/\.(\w+)$/; - my $embstyle=&Apache::loncommon::fileembstyle($1); - if (($embstyle eq 'img') || ($embstyle eq 'emb')) { - $url='/adm/wrapper'.$url; - } elsif ($embstyle eq 'ssi') { - #do nothing with these - } elsif ($url!~/\.(sequence|page)$/) { - $url='/adm/coursedocs/showdoc'.$url; - } - } elsif ($url=~m|^/ext/|) { - $url='/adm/wrapper'.$url; - $external = 1; - } - if (&Apache::lonnet::symbverify($symb,$url)) { - $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); - } else { - $url=''; - } - if ($container eq 'page') { - my $symb=$env{'form.pagesymb'}; - - $url=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($symb))[2]); - $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); + $url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/}; + if (!$supplementalflag && $residx && $symb) { + if ((!$isfolder) && (!$ispage)) { + (undef,undef,$url)=&Apache::lonnet::decode_symb($symb); + $url=&Apache::lonnet::clutter($url); + if ($url=~/^\/*uploaded\//) { + $url=~/\.(\w+)$/; + my $embstyle=&Apache::loncommon::fileembstyle($1); + if (($embstyle eq 'img') || ($embstyle eq 'emb')) { + $url='/adm/wrapper'.$url; + } elsif ($embstyle eq 'ssi') { + #do nothing with these + } elsif ($url!~/\.(sequence|page)$/) { + $url='/adm/coursedocs/showdoc'.$url; + } + } elsif ($url=~m|^/ext/|) { + $url='/adm/wrapper'.$url; + } + if (&Apache::lonnet::symbverify($symb,$url)) { + $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); + } else { + $url=''; + } } } - my ($parameterset,$rand_order_text) = (' ', ' '); - if ($isfolder || $extension eq 'sequence') { + my ($rand_pick_text,$rand_order_text); + if ($isfolder || $ispage || $extension eq 'sequence' || $extension eq 'page') { my $foldername=&escape($foldertitle); my $folderpath=$env{'form.folderpath'}; if ($folderpath) { $folderpath.='&' }; + if (!$allowed && $supplementalflag) { + $folderpath.=$containerarg.'&'.$foldername; + $url.='folderpath='.&escape($folderpath); + } else { # Append randompick number, hidden, and encrypted with ":" to foldername, # so it gets transferred between levels - $folderpath.=$folderarg.'&'.$foldername.':'.(&LONCAPA::map::getparameter($orderidx, + $folderpath.=$containerarg.'&'.$foldername. + ':'.(&LONCAPA::map::getparameter($orderidx, 'parameter_randompick'))[0] .':'.((&LONCAPA::map::getparameter($orderidx, 'parameter_hiddenresource'))[0]=~/^yes$/i) .':'.((&LONCAPA::map::getparameter($orderidx, 'parameter_encrypturl'))[0]=~/^yes$/i) .':'.((&LONCAPA::map::getparameter($orderidx, - 'parameter_randomorder'))[0]=~/^yes$/i); - $url.='folderpath='.&escape($folderpath).$cpinfo; - $parameterset='<label>'.&mt('Randomly Pick: '). - '<input type="text" size="4" onchange="this.form.changeparms.value='."'randompick'".';this.form.submit()" name="randompick_'.$orderidx.'" value="'. - (&LONCAPA::map::getparameter($orderidx, - 'parameter_randompick'))[0]. - '" />'. -'<a href="javascript:void(0)">'.&mt('Save').'</a></label>'; - my $ro_set= - ((&LONCAPA::map::getparameter($orderidx,'parameter_randomorder'))[0]=~/^yes$/i?' checked="checked"':''); - $rand_order_text =' -<span class="LC_nobreak"><label><input type="checkbox" name="randomorder_'.$orderidx.'" onclick="this.form.changeparms.value=\'randomorder\';this.form.submit()" '.$ro_set.' /> '.&mt('Random Order').' </label></span>'; - } - if ($ispage) { - my $pagename=&escape($pagetitle); - my $pagepath; - my $folderpath=$env{'form.folderpath'}; - if ($folderpath) { $pagepath = $folderpath.'&' }; - $pagepath.=$pagearg.'&'.$pagename; - my $symb=$env{'form.pagesymb'}; - if (!$symb) { - my $path='uploaded/'. - $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'. - $env{'course.'.$env{'request.course.id'}.'.num'}.'/'; - $symb=&Apache::lonnet::encode_symb($path.$folder.'.sequence', - $residx, - $path.$pagearg.'.page'); - } - $url.='pagepath='.&escape($pagepath). - '&pagesymb='.&escape($symb).$cpinfo; - } - if (($external) && ($allowed)) { - my $form = ($folder =~ /^default/)? 'newext' : 'supnewext'; - $external = ' <a class="LC_docs_ext_edit" href="javascript:edittext(\''.$form.'\',\''.$residx.'\',\''.&escape($title).'\',\''.&escape($orig_url).'\');" >'.&mt('Edit').'</a>'; - } else { - undef($external); + 'parameter_randomorder'))[0]=~/^yes$/i) + .':'.$ispage; + $url.='folderpath='.&escape($folderpath); + my $rpicknum = (&LONCAPA::map::getparameter($orderidx, + 'parameter_randompick'))[0]; + my $rpckchk; + if ($rpicknum) { + $rpckchk = ' checked="checked"'; + if (($ishash) && (ref($filtersref->{'randompick'}) eq 'ARRAY')) { + push(@{$filtersref->{'randompick'}},$orderidx.':'.$rpicknum); + } + } + my $formname = 'edit_randompick_'.$orderidx; + $rand_pick_text = +'<form action="/adm/coursedocs" method="post" name="'.$formname.'">'."\n". +$form_param."\n". +$form_common."\n". +'<span class="LC_nobreak"><label><input type="checkbox" name="randompick_'.$orderidx.'" id="randompick_'.$orderidx.'" onclick="'."updatePick(this.form,'$orderidx','check');".'"'.$rpckchk.' /> '.&mt('Randomly Pick').'</label><input type="hidden" name="rpicknum_'.$orderidx.'" id="rpicknum_'.$orderidx.'" value="'.$rpicknum.'" /><span id="randompicknum_'.$orderidx.'">'; + if ($rpicknum ne '') { + $rand_pick_text .= ': <a href="javascript:updatePick('."document.$formname,'$orderidx','link'".')">'.$rpicknum.'</a>'; + } + $rand_pick_text .= '</span></span>'. + $form_end; + my $ro_set; + if ((&LONCAPA::map::getparameter($orderidx,'parameter_randomorder'))[0]=~/^yes$/i) { + $ro_set = 'checked="checked"'; + if (($ishash) && (ref($filtersref->{'randomorder'}) eq 'ARRAY')) { + push(@{$filtersref->{'randomorder'}},$orderidx); + } + } + $formname = 'edit_rorder_'.$orderidx; + $rand_order_text = +'<form action="/adm/coursedocs" method="post" name="'.$formname.'">'."\n". +$form_param."\n". +$form_common."\n". +'<span class="LC_nobreak"><label><input type="checkbox" name="randomorder_'.$orderidx.'" id="randomorder_'.$orderidx.'" onclick="checkForSubmit(this.form,'."'randomorder','settings'".');" '.$ro_set.' /> '.&mt('Random Order').' </label></span>'. +$form_end; + } + } elsif ($supplementalflag && !$allowed) { + $url .= ($url =~ /\?/) ? '&':'?'; + $url .= 'folderpath='.&HTML::Entities::encode($esc_path,'<>&"'); + if ($title) { + $url .= '&title='.&HTML::Entities::encode($renametitle,'<>&"'); + } + if ($isexternal && $orderidx) { + $url .= '&idx='.$orderidx; + } + } + my ($tdalign,$tdwidth); + if ($allowed) { + my $fileloc = + &Apache::lonnet::declutter(&Apache::lonnet::filelocation('',$orig_url)); + if ($isexternal) { + ($editlink,$extresform) = + &Apache::lonextresedit::extedit_form(0,$residx,$orig_url,$title,$pathitem); + } elsif (!$isfolder && !$ispage) { + my ($cfile,$home,$switchserver,$forceedit,$forceview) = + &Apache::lonnet::can_edit_resource($fileloc,$coursenum,$coursedom,$orig_url); + if (($cfile ne '') && ($symb ne '' || $supplementalflag)) { + my $jscall = + &Apache::lonhtmlcommon::jump_to_editres($cfile,$home, + $switchserver, + $forceedit, + undef,$symb, + &escape($env{'form.folderpath'}), + $renametitle,'','',1); + if ($jscall) { + $editlink = '<a class="LC_docs_ext_edit" href="javascript:'. + $jscall.'" >'.&mt('Edit').'</a> '."\n"; + } + } + } + $tdalign = ' align="right" valign="top"'; + $tdwidth = ' width="80%"'; } my $reinit; if ($crstype eq 'Community') { $reinit = &mt('(re-initialize community to access)'); } else { $reinit = &mt('(re-initialize course to access)'); - } - $line.=' - <td> - '.($url?'<a href="'.$url.'">':'').'<img src="'.$icon.'" alt="" class="LC_icon" />'.($url?'</a>':'').' - </td> - <td> - '.($url?"<a href=\"$url\">":'').$title.($url?'</a>':' <span class="LC_docs_reinit_warn">'.$reinit.'</span>').$external." - </td>"; + } + $line.='<td class="LC_docs_entry_commands"'.$tdalign.'><span class="LC_nobreak">'.$editlink.$renamelink; + if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) { + $line.='<a href="'.$url.'"><img src="'.$icon.'" alt="" class="LC_icon" /></a>'; + } elsif ($url) { + $line.=&Apache::loncommon::modal_link($url.(($url=~/\?/)?'&':'?').'inhibitmenu=yes', + '<img src="'.$icon.'" alt="" class="LC_icon" />',600,500); + } else { + $line.='<img src="'.$icon.'" alt="" class="LC_icon" />'; + } + $line.='</span></td><td'.$tdwidth.'>'; + if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) { + $line.='<a href="'.$url.'">'.$title.'</a>'; + } elsif ($url) { + $line.=&Apache::loncommon::modal_link($url.(($url=~/\?/)?'&':'?').'inhibitmenu=yes', + $title,600,500); + } else { + $line.=$title.' <span class="LC_docs_reinit_warn">'.$reinit.'</span>'; + } + $line.="$extresform</td>"; + $rand_pick_text = ' ' if ($rand_pick_text eq ''); + $rand_order_text = ' ' if ($rand_order_text eq ''); if (($allowed) && ($folder!~/^supplemental/)) { my %lt=&Apache::lonlocal::texthash( 'hd' => 'Hidden', 'ec' => 'URL hidden'); - my $enctext= - ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i?' checked="checked"':''); - my $hidtext= - ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i?' checked="checked"':''); + my ($enctext,$hidtext); + if ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i) { + $enctext = ' checked="checked"'; + if (($ishash) && (ref($filtersref->{'encrypturl'}) eq 'ARRAY')) { + push(@{$filtersref->{'encrypturl'}},$orderidx); + } + } + if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) { + $hidtext = ' checked="checked"'; + if (($ishash) && (ref($filtersref->{'randomorder'}) eq 'ARRAY')) { + push(@{$filtersref->{'hiddenresource'}},$orderidx); + } + } + my $formhidden = 'edit_hiddenresource_'.$orderidx; + my $formurlhidden = 'edit_encrypturl_'.$orderidx; $line.=(<<ENDPARMS); <td class="LC_docs_entry_parameter"> - $form_start - <label><input type="checkbox" name="hiddenresource_$orderidx" onclick="this.form.changeparms.value='hiddenresource';this.form.submit()" $hidtext /> $lt{'hd'}</label> + <form action="/adm/coursedocs" method="post" name="$formhidden"> + $form_param + $form_common + <label><input type="checkbox" name="hiddenresource_$orderidx" id="hiddenresource_$orderidx" onclick="checkForSubmit(this.form,'hiddenresource','settings');" $hidtext /> $lt{'hd'}</label> $form_end - </td> - <td class="LC_docs_entry_parameter"> - $form_start - <label><input type="checkbox" name="encrypturl_$orderidx" onclick="this.form.changeparms.value='encrypturl';this.form.submit()" $enctext /> $lt{'ec'}</label> + <br /> + <form action="/adm/coursedocs" method="post" name="$formurlhidden"> + $form_param + $form_common + <label><input type="checkbox" name="encrypturl_$orderidx" id="encrypturl_$orderidx" onclick="checkForSubmit(this.form,'encrypturl','settings');" $enctext /> $lt{'ec'}</label> $form_end </td> - <td class="LC_docs_entry_parameter">$form_start $rand_order_text $form_end</td> - <td class="LC_docs_entry_parameter">$form_start $parameterset $form_end</td> + <td class="LC_docs_entry_parameter">$rand_pick_text<br /> + $rand_order_text</td> ENDPARMS } $line.=&Apache::loncommon::end_data_table_row(); return $line; } +sub action_restrictions { + my ($cnum,$cdom,$url,$folderpath,$currgroups) = @_; + my %denied = ( + cut => 0, + copy => 0, + remove => 0, + ); + if ($url=~ m{^/res/.+\.(page|sequence)$}) { + # no copy for published maps + $denied{'copy'} = 1; + } elsif ($url=~m{^/res/lib/templates/}) { + $denied{'copy'} = 1; + $denied{'cut'} = 1; + } elsif ($url eq "/uploaded/$cdom/$cnum/group_allfolders.sequence") { + if ($folderpath =~ /^default&[^\&]+$/) { + if ((ref($currgroups) eq 'HASH') && (keys(%{$currgroups}) > 0)) { + $denied{'remove'} = 1; + } + $denied{'cut'} = 1; + $denied{'copy'} = 1; + } + } elsif ($url =~ m{^\Q/uploaded/$cdom/$cnum/group_folder_\E(\w+)\.sequence$}) { + my $group = $1; + if ($folderpath =~ /^default&[^\&]+\&group_allfolders\&[^\&]+$/) { + if ((ref($currgroups) eq 'HASH') && (exists($currgroups->{$group}))) { + $denied{'remove'} = 1; + } + } + $denied{'cut'} = 1; + $denied{'copy'} = 1; + } elsif ($url =~ m{^\Q/adm/$cdom/$cnum/\E(\w+)/smppg$}) { + my $group = $1; + if ($folderpath =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&\Qgroup_folder_$group\E\&[^\&]+$/) { + if ((ref($currgroups) eq 'HASH') && (exists($currgroups->{$group}))) { + my %groupsettings = &Apache::longroup::get_group_settings($currgroups->{$group}); + if (keys(%groupsettings) > 0) { + $denied{'remove'} = 1; + } + $denied{'cut'} = 1; + $denied{'copy'} = 1; + } + } + } elsif ($folderpath =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&group_folder_(\w+)\&/) { + my $group = $1; + if ($url =~ /group_boards_\Q$group\E/) { + if ((ref($currgroups) eq 'HASH') && (exists($currgroups->{$group}))) { + my %groupsettings = &Apache::longroup::get_group_settings($currgroups->{$group}); + if (keys(%groupsettings) > 0) { + if (ref($groupsettings{'functions'}) eq 'HASH') { + if ($groupsettings{'functions'}{'discussion'} eq 'on') { + $denied{'remove'} = 1; + } + } + } + $denied{'cut'} = 1; + $denied{'copy'} = 1; + } + } + } + return %denied; +} + +sub new_timebased_suffix { + my ($dom,$num,$type,$area,$container) = @_; + my ($prefix,$namespace,$idtype,$errtext,$locknotfreed); + if ($type eq 'paste') { + $prefix = $type; + $namespace = 'courseeditor'; + } elsif ($type eq 'map') { + $prefix = 'docs'; + if ($area eq 'supplemental') { + $prefix = 'supp'; + } + $prefix .= $container; + $namespace = 'uploadedmaps'; + } else { + $prefix = $type; + $namespace = 'templated'; + } + $idtype = 'concat'; + my ($suffix,$freedlock,$error) = + &Apache::lonnet::get_timebased_id($prefix,'num',$namespace,$dom,$num); + if (!$suffix) { + if ($type eq 'paste') { + $errtext = &mt('Failed to acquire a unique timestamp-based suffix when adding to the paste buffer.'); + } elsif ($type eq 'map') { + $errtext = &mt('Failed to acquire a unique timestamp-based suffix for the new folder/page.'); + } elsif ($type eq 'smppg') { + $errtext = &mt('Failed to acquire a unique timestamp-based suffix for the new simple page.'); + } else { + $errtext = &mt('Failed to acquire a unique timestamp-based suffix for the new discussion board.'); + } + if ($error) { + $errtext .= '<br />'.$error; + } + } + if ($freedlock ne 'ok') { + $locknotfreed = + '<div class="LC_error">'. + &mt('There was a problem removing a lockfile.').' '; + if ($type eq 'paste') { + &mt('This will prevent use of the paste buffer until th next log-in.'); + } elsif ($type eq 'map') { + &mt('This will prevent creation of additional folders or composite pages in this course.'); + } elsif ($type eq 'smppg') { + $locknotfreed .= + &mt('This will prevent creation of additional simple pages in this course.'); + } else { + $locknotfreed .= + &mt('This will prevent creation of additional discussion boards in this course.'); + } + unless ($type eq 'paste') { + $locknotfreed .= + ' '.&mt('Please contact the [_1]helpdesk[_2] for assistance.', + '<a href="/adm/helpdesk" target="_helpdesk">','</a>'); + } + $locknotfreed .= '</div>'; + } + return ($suffix,$errtext,$locknotfreed); +} + =pod =item tiehash() @@ -2211,7 +3973,7 @@ sub checkonthis { $r->print('<span class="LC_error">'.&mt('connection down').'</span>'); } elsif ($result eq 'not_found') { unless ($url=~/\$/) { - $r->print('<span class="LC_error">'.&mt('not found').'</b></span>'); + $r->print('<span class="LC_error">'.&mt('not found').'</span>'); } else { $r->print('<span class="LC_error">'.&mt('unable to verify variable URL').'</span>'); } @@ -2228,7 +3990,7 @@ sub checkonthis { =item list_symbs() -List Symbs +List Content Identifiers =cut @@ -2236,8 +3998,9 @@ sub list_symbs { my ($r) = @_; my $crstype = &Apache::loncommon::course_type(); - $r->print(&Apache::loncommon::start_page('Symb List')); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('Symb List')); + $r->print(&Apache::loncommon::start_page('List of Content Identifiers')); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content Identifiers')); + $r->print(&startContentScreen('tools')); my $navmap = Apache::lonnavmaps::navmap->new(); if (!defined($navmap)) { $r->print('<h2>'.&mt('Retrieval of List Failed').'</h2>'. @@ -2246,25 +4009,42 @@ sub list_symbs { '</div>'); &Apache::lonnet::logthis('Symb list failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'}); } else { - $r->print("<pre>\n"); + $r->print('<h4 class="LC_info">'.&mt("$crstype Content Identifiers").'</h4>'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '<th>'.&mt('Title').'</th><th>'.&mt('Identifier').'</th>'. + &Apache::loncommon::end_data_table_header_row()."\n"); + my $count; foreach my $res ($navmap->retrieveResources()) { - $r->print($res->compTitle()."\t".$res->symb()."\n"); + $r->print(&Apache::loncommon::start_data_table_row(). + '<td>'.$res->compTitle().'</td>'. + '<td>'.$res->symb().'</td>'. + &Apache::loncommon::end_data_table_row()); + $count ++; } - $r->print("\n</pre>\n"); + if (!$count) { + $r->print(&Apache::loncommon::start_data_table_row(). + '<td colspan="2">'.&mt("$crstype is empty").'</td>'. + &Apache::loncommon::end_data_table_row()); + } + $r->print(&Apache::loncommon::end_data_table()); } - $r->print('<hr /><a href="/adm/coursedocs">'.&mt('Back to Course Editor').'</a>'); + $r->print(&endContentScreen()); } sub verifycontent { my ($r) = @_; my $crstype = &Apache::loncommon::course_type(); - $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Documents')); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Documents')); + $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Content')); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Content')); + $r->print(&startContentScreen('tools')); + $r->print('<h4 class="LC_info">'.&mt($crstype.' content verification').'</h4>'); $hashtied=0; undef %alreadyseen; %alreadyseen=(); &tiehash(); + foreach my $key (keys(%hash)) { if ($hash{$key}=~/\.(page|sequence)$/) { if (($key=~/^src_/) && ($alreadyseen{&unescape($hash{$key})})) { @@ -2279,13 +4059,8 @@ sub verifycontent { } } &untiehash(); - $r->print( - '<p class="LC_success">'.&mt('Done').'</p>' - .'<hr />' - .'<p><a href="/adm/coursedocs">' - .&mt('Back to Course Editor') - .'</a></p>' - ); + $r->print('<p class="LC_success">'.&mt('Done').'</p>'); + $r->print(&endContentScreen()); } @@ -2298,8 +4073,10 @@ sub devalidateversioncache { sub checkversions { my ($r) = @_; my $crstype = &Apache::loncommon::course_type(); - $r->print(&Apache::loncommon::start_page("Check $crstype Document Versions")); - $r->print(&Apache::lonhtmlcommon::breadcrumbs("Check $crstype Document Versions")); + $r->print(&Apache::loncommon::start_page("Check $crstype Resource Versions")); + $r->print(&Apache::lonhtmlcommon::breadcrumbs("Check $crstype Resource Versions")); + $r->print(&startContentScreen('tools')); + my $header=''; my $startsel=''; my $monthsel=''; @@ -2351,17 +4128,19 @@ sub checkversions { if (&Apache::lonnet::put('resourceversions',\%newsetversions, $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') { - $r->print('<h1>'.&mt('Your Version Settings have been Saved').'</h1>'); + $r->print(&Apache::loncommon::confirmwrapper( + &Apache::lonhtmlcommon::confirm_success(&mt('Your Version Settings have been Saved')))); } else { - $r->print('<h1><span class="LC_error">'.&mt('An Error Occured while Attempting to Save your Version Settings').'</span></h1>'); + $r->print(&Apache::loncommon::confirmwrapper( + &Apache::lonhtmlcommon::confirm_success(&mt('An Error Occured while Attempting to Save your Version Settings'),1))); } &mark_hash_old(); } &changewarning($r,''); if ($env{'form.timerange'} eq 'all') { # show all documents - $header=&mt('All Documents in '.$crstype); - $allsel=1; + $header=&mt('All content in '.$crstype); + $allsel=' selected="selected"'; foreach my $key (keys(%hash)) { if ($key=~/^ids\_(\/res\/.+)$/) { my $src=$1; @@ -2382,19 +4161,19 @@ sub checkversions { .&mt('seconds'); if ($env{'form.timerange'}==-1) { $seltext='since start of course'; - $startsel='selected'; + $startsel=' selected="selected"'; $env{'form.timerange'}=time; } $starttime=time-$env{'form.timerange'}; if ($env{'form.timerange'}==2592000) { $seltext=&mt('during the last month').' ('.&Apache::lonlocal::locallocaltime($starttime).')'; - $monthsel='selected'; + $monthsel=' selected="selected"'; } elsif ($env{'form.timerange'}==604800) { $seltext=&mt('during the last week').' ('.&Apache::lonlocal::locallocaltime($starttime).')'; - $weeksel='selected'; + $weeksel=' selected="selected"'; } elsif ($env{'form.timerange'}==86400) { $seltext=&mt('since yesterday').' ('.&Apache::lonlocal::locallocaltime($starttime).')'; - $daysel='selected'; + $daysel=' selected="selected"'; } $header=&mt('Content changed').' '.$seltext; } else { @@ -2410,6 +4189,7 @@ sub checkversions { 'lw' => 'Version changes since last Week', 'sy' => 'Version changes since Yesterday', 'al' => 'All Resources (possibly large output)', + 'cd' => 'Change display', 'sd' => 'Display', 'fi' => 'File', 'md' => 'Modification Date', @@ -2419,125 +4199,146 @@ sub checkversions { 'sv' => 'Set Versions to be used in '.$crstype.' according to Selections below', 'sm' => 'Keep all Resources up-to-date with most recent Versions (default)', 'sc' => 'Set all Resource Versions to current Version (Fix Versions)', - 'di' => 'Differences'); + 'di' => 'Differences', + 'save' => 'Save changes', + 'vers' => 'Version choice(s) for specific resources', + 'act' => 'Actions'); $r->print(<<ENDHEADERS); +<h4 class="LC_info">$header</h4> <form action="/adm/coursedocs" method="post"> <input type="hidden" name="versions" value="1" /> -<input type="submit" name="setmostrecent" value="$lt{'sm'}" /> -<input type="submit" name="setcurrent" value="$lt{'sc'}" /><hr /> +<div class="LC_left_float"> +<fieldset> +<legend>$lt{'cd'}</legend> <select name="timerange"> -<option value='all' $allsel>$lt{'al'}</option> -<option value="-1" $startsel>$lt{'st'}</option> -<option value="2592000" $monthsel>$lt{'lm'}</option> -<option value="604800" $weeksel>$lt{'lw'}</option> -<option value="86400" $daysel>$lt{'sy'}</option> +<option value='all'$allsel>$lt{'al'}</option> +<option value="-1"$startsel>$lt{'st'}</option> +<option value="2592000"$monthsel>$lt{'lm'}</option> +<option value="604800"$weeksel>$lt{'lw'}</option> +<option value="86400"$daysel>$lt{'sy'}</option> </select> <input type="submit" name="display" value="$lt{'sd'}" /> -<h3>$header</h3> -<input type="submit" name="setversions" value="$lt{'sv'}" /> -<table border="0"> +</fieldset> +</div> +<div class="LC_left_float"> +<fieldset> +<legend>$lt{'act'}</legend> +$lt{'sm'}: <input type="submit" name="setmostrecent" value="Go" /><br /> +$lt{'sc'}: <input type="submit" name="setcurrent" value="Go" /> +</fieldset> +</div> +<br clear="all" /> +<hr /> +<h4>$lt{'vers'}</h4> ENDHEADERS - foreach my $key (sort(keys(%changes))) { - if ($changes{$key}>$starttime) { - my ($root,$extension)=($key=~/^(.*)\.(\w+)$/); - my $currentversion=&Apache::lonnet::getversion($key); - if ($currentversion<0) { - $currentversion=&mt('Could not be determined.'); - } - my $linkurl=&Apache::lonnet::clutter($key); - $r->print( - '<tr><td colspan="5"><br /><br /><font size="+1"><b>'. - &Apache::lonnet::gettitle($linkurl). - '</b></font></td></tr>'. - '<tr><td> </td>'. - '<td colspan="4">'. - '<a href="'.$linkurl.'" target="cat">'.$linkurl. - '</a></td></tr>'. - '<tr><td></td>'. - '<td title="'.$lt{'md'}.'">'. - &Apache::lonlocal::locallocaltime( - &Apache::lonnet::metadata($root.'.'.$extension, - 'lastrevisiondate') - ). - '</td>'. - '<td title="'.$lt{'mr'}.'"><span class="LC_nobreak">Most Recent: '. - '<font size="+1">'.$currentversion.'</font>'. - '</span></td>'. - '<td title="'.$lt{'ve'}.'"><span class="LC_nobreak">In '.$crstype.': '. - '<font size="+1">'); -# Used in course - my $usedversion=$hash{'version_'.$linkurl}; - if (($usedversion) && ($usedversion ne 'mostrecent')) { - $r->print($usedversion); - } else { - $r->print($currentversion); - } - $r->print('</font></span></td><td title="'.$lt{'vu'}.'">'. - '<span class="LC_nobreak">Use: '); -# Set version - $r->print(&Apache::loncommon::select_form($setversions{$linkurl}, - 'set_version_'.$linkurl, - {'select_form_order' => - ['',1..$currentversion,'mostrecent'], - '' => '', - 'mostrecent' => &mt('most recent'), - map {$_,$_} (1..$currentversion)})); - $r->print('</span></td></tr><tr><td></td>'); - my $lastold=1; - for (my $prevvers=1;$prevvers<$currentversion;$prevvers++) { - my $url=$root.'.'.$prevvers.'.'.$extension; - if (&Apache::lonnet::metadata($url,'lastrevisiondate')< - $starttime) { - $lastold=$prevvers; - } - } - # - # Code to figure out how many version entries should go in - # each of the four columns - my $entries_per_col = 0; - my $num_entries = ($currentversion-$lastold); - if ($num_entries % 4 == 0) { - $entries_per_col = $num_entries/4; - } else { - $entries_per_col = $num_entries/4 + 1; - } - my $entries_count = 0; - $r->print('<td valign="top"><font size="-2">'); - my $cols_output = 1; + #number of columns for version history + my %changedbytime; + foreach my $key (keys(%changes)) { + #excludes not versionable problems from resource version history: + next if ($key =~ /^\/res\/lib\/templates/); + my $chg; + if ($env{'form.timerange'} eq 'all') { + my ($root,$extension)=($key=~/^(.*)\.(\w+)$/); + $chg = &Apache::lonnet::metadata($root.'.'.$extension,'lastrevisiondate'); + } else { + $chg = $changes{$key}; + next if ($chg < $starttime); + } + push(@{$changedbytime{$chg}},$key); + } + if (keys(%changedbytime) == 0) { + &untiehash(); + $r->print(&mt('No content changes in imported content in specified time frame'). + &endContentScreen()); + return; + } + $r->print( + '<input type="submit" name="setversions" value="'.$lt{'save'}.'" />'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '<th>'.&mt('Resources').'</th>'. + "<th>$lt{'mr'}</th>". + "<th>$lt{'ve'}</th>". + "<th>$lt{'vu'}</th>". + '<th>'.&mt('History').'</th>'. + &Apache::loncommon::end_data_table_header_row() + ); + foreach my $chg (sort {$b <=> $a } keys(%changedbytime)) { + foreach my $key (sort(@{$changedbytime{$chg}})) { + my ($root,$extension)=($key=~/^(.*)\.(\w+)$/); + my $currentversion=&Apache::lonnet::getversion($key); + if ($currentversion<0) { + $currentversion='<span class="LC_error">'.&mt('Could not be determined.').'</span>'; + } + my $linkurl=&Apache::lonnet::clutter($key); + $r->print( + &Apache::loncommon::start_data_table_row(). + '<td><b>'.&Apache::lonnet::gettitle($linkurl).'</b><br />'. + '<a href="'.$linkurl.'" target="cat">'.$linkurl.'</a></td>'. + '<td align="right">'.$currentversion.'<span class="LC_fontsize_medium"><br />('. + &Apache::lonlocal::locallocaltime($chg).')</span></td>'. + '<td align="right">' + ); + # Used in course + my $usedversion=$hash{'version_'.$linkurl}; + if (($usedversion) && ($usedversion ne 'mostrecent')) { + if ($usedversion != $currentversion) { + $r->print('<span class="LC_warning">'.$usedversion.'</span>'); + } else { + $r->print($usedversion); + } + } else { + $r->print($currentversion); + } + $r->print('</td><td title="'.$lt{'vu'}.'">'); + # Set version + $r->print(&Apache::loncommon::select_form( + $setversions{$linkurl}, + 'set_version_'.$linkurl, + {'select_form_order' => ['',1..$currentversion,'mostrecent'], + '' => '', + 'mostrecent' => &mt('most recent'), + map {$_,$_} (1..$currentversion)})); + my $lastold=1; + for (my $prevvers=1;$prevvers<$currentversion;$prevvers++) { + my $url=$root.'.'.$prevvers.'.'.$extension; + if (&Apache::lonnet::metadata($url,'lastrevisiondate')<$starttime) { + $lastold=$prevvers; + } + } + $r->print('</td>'); + # List all available versions + $r->print('<td valign="top"><span class="LC_fontsize_medium">'); for (my $prevvers=$lastold;$prevvers<$currentversion;$prevvers++) { - my $url=$root.'.'.$prevvers.'.'.$extension; - $r->print('<span class="LC_nobreak"><a href="'.&Apache::lonnet::clutter($url). - '">'.&mt('Version').' '.$prevvers.'</a> ('. - &Apache::lonlocal::locallocaltime( - &Apache::lonnet::metadata($url, - 'lastrevisiondate') - ). - ')'); - if (&Apache::loncommon::fileembstyle($extension) eq 'ssi') { - $r->print(' <a href="/adm/diff?filename='. - &Apache::lonnet::clutter($root.'.'.$extension). - '&versionone='.$prevvers. - '">'.&mt('Diffs').'</a>'); - } - $r->print('</span><br />'); - if (++$entries_count % $entries_per_col == 0) { - $r->print('</font></td>'); - if ($cols_output != 4) { - $r->print('<td valign="top"><font size="-2">'); - $cols_output++; - } + my $url=$root.'.'.$prevvers.'.'.$extension; + $r->print( + '<span class="LC_nobreak">' + .'<a href="'.&Apache::lonnet::clutter($url).'">' + .&mt('Version [_1]',$prevvers).'</a>' + .' ('.&Apache::lonlocal::locallocaltime( + &Apache::lonnet::metadata($url,'lastrevisiondate')) + .')'); + if (&Apache::loncommon::fileembstyle($extension) eq 'ssi') { + $r->print( + ' <a href="/adm/diff?filename='. + &Apache::lonnet::clutter($root.'.'.$extension). + &HTML::Entities::encode('&versionone='.$prevvers,'"<>&'). + '" target="diffs">'.&mt('Diffs').'</a>'); } - } - while($cols_output++ < 4) { - $r->print('</font></td><td><font>') + $r->print('</span><br />'); } - $r->print('</font></td></tr>'."\n"); - } + $r->print('</span></td>'.&Apache::loncommon::end_data_table_row()); + } } - $r->print('</table></form>'); - $r->print('<p class="LC_success">'.&mt('Done').'</p>'); + $r->print( + &Apache::loncommon::end_data_table(). + '<input type="submit" name="setversions" value="'.$lt{'save'}.'" />'. + '</form>' + ); &untiehash(); + $r->print(&endContentScreen()); + return; } sub mark_hash_old { @@ -2569,11 +4370,6 @@ sub changewarning { my $pathvar='folderpath'; my $path=&escape($env{'form.folderpath'}); if (!defined($url)) { - if (defined($env{'form.pagepath'})) { - $pathvar='pagepath'; - $path=&escape($env{'form.pagepath'}); - $path.='&pagesymb='.&escape($env{'form.pagesymb'}); - } $url='/adm/coursedocs?'.$pathvar.'='.$path; } my $course_type = &Apache::loncommon::course_type(); @@ -2597,37 +4393,98 @@ $help{'Caching'}.'</p></form>'."\n\n"); sub init_breadcrumbs { - my ($form,$text)=@_; + my ($form,$text,$help)=@_; &Apache::lonhtmlcommon::clear_breadcrumbs(); - &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs", + &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?tools=1", text=>&Apache::loncommon::course_type().' Editor', faq=>273, bug=>'Instructor Interface', - help => 'Docs_Adding_Course_Doc'}); + help => $help}); &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?".$form.'=1', text=>$text, faq=>273, bug=>'Instructor Interface'}); } +# subroutine to list form elements +sub create_list_elements { + my @formarr = @_; + my $list = ''; + foreach my $button (@formarr){ + foreach my $picture (keys(%{$button})) { + $list .= &Apache::lonhtmlcommon::htmltag('li', $picture.' '.$button->{$picture}, {class => 'LC_menubuttons_inline_text', id => ''}); + } + } + return $list; +} +# subroutine to create ul from list elements +sub create_form_ul { + my $list = shift; + my $ul = &Apache::lonhtmlcommon::htmltag('ul',$list, {class => 'LC_ListStyleNormal'}); + return $ul; +} +# +# Start tabs +# + +sub startContentScreen { + my ($mode) = @_; + my $output = '<ul class="LC_TabContentBigger" id="mainnav">'; + if (($mode eq 'navmaps') || ($mode eq 'supplemental')) { + $output .= '<li'.(($mode eq 'navmaps')?' class="active"':'').'><a href="/adm/navmaps"><b> '.&mt('Content Overview').' </b></a></li>'."\n"; + $output .= '<li'.(($mode eq 'coursesearch')?' class="active"':'').'><a href="/adm/searchcourse"><b> '.&mt('Content Search').' </b></a></li>'."\n"; + $output .= '<li'.(($mode eq 'courseindex')?' class="active"':'').'><a href="/adm/indexcourse"><b> '.&mt('Content Index').' </b></a></li>'."\n"; + $output .= '<li '.(($mode eq 'suppdocs')?' class="active"':'').'><a href="/adm/supplemental"><b>'.&mt('Supplemental Content').'</b></a></li>'; + } else { + $output .= '<li '.(($mode eq 'docs')?' class="active"':'').' id="tabbededitor"><a href="/adm/coursedocs?forcestandard=1"><b> '.&mt('Main Content Editor').' </b></a></li>'."\n"; + $output .= '<li '.(($mode eq 'suppdocs')?' class="active"':'').'><a href="/adm/coursedocs?forcesupplement=1"><b>'.&mt('Supplemental Content Editor').'</b></a></li>'."\n"; + $output .= '<li '.(($mode eq 'tools')?' class="active"':'').'><a href="/adm/coursedocs?tools=1"><b> '.&mt('Content Utilities').' </b></a></li>'."\n"; + '><a href="/adm/coursedocs?tools=1"><b> '.&mt('Content Utilities').' </b></a></li>'; + } + $output .= "\n".'</ul>'."\n"; + $output .= '<div class="LC_DocsBox" style="clear:both;margin:0;" id="contenteditor">'. + '<div id="maincoursedoc" style="margin:0 0;padding:0 0;">'. + '<div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">'; + return $output; +} + +# +# End tabs +# + +sub endContentScreen { + return '</div></div></div>'; +} + +sub supplemental_base { + return 'supplemental&'.&escape(&mt('Supplemental Content')); +} sub handler { my $r = shift; &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK if $r->header_only; + +# get course data my $crstype = &Apache::loncommon::course_type(); + my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'}; + my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'}; +# graphics settings + $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL').'/'); +# # --------------------------------------------- Initialize help topics for this foreach my $topic ('Adding_Course_Doc','Main_Course_Documents', 'Adding_External_Resource','Navigate_Content', 'Adding_Folders','Docs_Overview', 'Load_Map', 'Supplemental','Score_Upload_Form','Adding_Pages', - 'Importing_LON-CAPA_Resource','Uploading_From_Harddrive', - 'Check_Resource_Versions','Verify_Content') { + 'Importing_LON-CAPA_Resource','Importing_IMS_Course', + 'Uploading_From_Harddrive','Course_Roster','Web_Page', + 'Dropbox','Simple_Problem') { $help{$topic}=&Apache::loncommon::help_open_topic('Docs_'.$topic); } # Composite help files @@ -2635,155 +4492,233 @@ sub handler { 'Docs_About_Syllabus,Docs_Editing_Templated_Pages'); $help{'Simple Page'} = &Apache::loncommon::help_open_topic( 'Docs_About_Simple_Page,Docs_Editing_Templated_Pages'); - $help{'Simple Problem'} = &Apache::loncommon::help_open_topic( - 'Option_Response_Simple'); $help{'Bulletin Board'} = &Apache::loncommon::help_open_topic( 'Docs_About_Bulletin_Board,Docs_Editing_Templated_Pages'); $help{'My Personal Information Page'} = &Apache::loncommon::help_open_topic( 'Docs_About_My_Personal_Info,Docs_Editing_Templated_Pages'); $help{'Group Portfolio'} = &Apache::loncommon::help_open_topic('Docs_About_Group_Files'); $help{'Caching'} = &Apache::loncommon::help_open_topic('Caching'); + + my $allowed; +# URI is /adm/supplemental when viewing supplemental docs in non-edit mode. + unless ($r->uri eq '/adm/supplemental') { + # does this user have privileges to modify content. + $allowed = &Apache::lonnet::allowed('mdc',$env{'request.course.id'}); + } -# does this user have privileges to modify docs - my $allowed=&Apache::lonnet::allowed('mdc',$env{'request.course.id'}); + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['inhibitmenu']); if ($allowed && $env{'form.verify'}) { - &init_breadcrumbs('verify','Verify Content'); + &init_breadcrumbs('verify','Verify Content','Docs_Verify_Content'); &verifycontent($r); } elsif ($allowed && $env{'form.listsymbs'}) { - &init_breadcrumbs('listsymbs','List Symbs'); + &init_breadcrumbs('listsymbs','List Content IDs'); &list_symbs($r); } elsif ($allowed && $env{'form.docslog'}) { &init_breadcrumbs('docslog','Show Log'); - &docs_change_log($r); + my $folder = $env{'form.folder'}; + if ($folder eq '') { + $folder='default'; + } + &docs_change_log($r,$coursenum,$coursedom,$folder,$allowed,$crstype,$iconpath); } elsif ($allowed && $env{'form.versions'}) { - &init_breadcrumbs('versions','Check/Set Resource Versions'); + &init_breadcrumbs('versions','Check/Set Resource Versions','Docs_Check_Resource_Versions'); &checkversions($r); } elsif ($allowed && $env{'form.dumpcourse'}) { - &init_breadcrumbs('dumpcourse','Dump '.&Apache::loncommon::course_type().' Documents to Construction Space'); + &init_breadcrumbs('dumpcourse','Copy '.&Apache::loncommon::course_type().' Content to Authoring Space'); &dumpcourse($r); } elsif ($allowed && $env{'form.exportcourse'}) { &init_breadcrumbs('exportcourse','IMS Export'); - &exportcourse($r); + &Apache::imsexport::exportcourse($r); } else { -# is this a standard course? +# +# Done catching special calls +# The whole rest is for course and supplemental documents and utilities menu +# Get the parameters that may be needed +# + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['folderpath', + 'forcesupplement','forcestandard', + 'tools','symb','command','supppath']); + +# standard=1: this is a "new-style" course with an uploaded map as top level +# standard=2: this is a "old-style" course, and there is nothing we can do my $standard=($env{'request.course.uri'}=~/^\/uploaded\//); - my $forcestandard = 0; - my $forcesupplement; + +# Decide whether this should display supplemental or main content or utilities +# supplementalflag=1: show supplemental documents +# supplementalflag=0: show standard documents +# toolsflag=1: show utilities + + my $unesc_folderpath = &unescape($env{'form.folderpath'}); + my $supplementalflag=($unesc_folderpath=~/^supplemental/); + if (($unesc_folderpath=~/^default/) || ($unesc_folderpath eq "")) { + $supplementalflag=0; + } + if ($env{'form.forcesupplement'}) { $supplementalflag=1; } + if ($env{'form.forcestandard'}) { $supplementalflag=0; } + unless ($allowed) { $supplementalflag=1; } + unless ($standard) { $supplementalflag=1; } + my $toolsflag=0; + if ($env{'form.tools'}) { $toolsflag=1; } + my $script=''; my $showdoc=0; + my $addentries = {}; + my $container; my $containertag; - my $uploadtag; + my $pathitem; +# Do we directly jump somewhere? - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['folderpath','pagepath', - 'pagesymb']); -# No folderpath, no pagepath, see if we have something stored - if ((!$env{'form.folderpath'}) && (!$env{'form.pagepath'})) { - &Apache::loncommon::restore_course_settings('docs_folderpath', - {'folderpath' => 'scalar'}); + if (($env{'form.command'} eq 'direct') || ($env{'form.command'} eq 'directnav')) { + if ($env{'form.symb'} ne '') { + $env{'form.folderpath'}= + &Apache::loncommon::symb_to_docspath($env{'form.symb'}); + &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => + $env{'form.command'}.'_'.$env{'form.symb'}}); + } elsif ($env{'form.supppath'} ne '') { + $env{'form.folderpath'}=$env{'form.supppath'}; + &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => + $env{'form.command'}.'_'.$env{'form.supppath'}}); + } + } elsif ($env{'form.command'} eq 'editdocs') { + $env{'form.folderpath'} = 'default&'. + &escape(&mt('Main Content').':::::'); + &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => $env{'form.command'}}); + } elsif ($env{'form.command'} eq 'editsupp') { + $env{'form.folderpath'} = 'supplemental&'. + &escape('Supplemental Content'); + &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => '/adm/supplemental'}); + } elsif ($env{'form.command'} eq 'contents') { + &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => '/adm/navmaps'}); + } elsif ($env{'form.command'} eq 'home') { + &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => '/adm/menu'}); + } + + +# Where do we store these for when we come back? + my $stored_folderpath='docs_folderpath'; + if ($supplementalflag) { + $stored_folderpath='docs_sup_folderpath'; + } + +# No folderpath, and in edit mode, see if we have something stored + if ((!$env{'form.folderpath'}) && $allowed) { + &Apache::loncommon::restore_course_settings($stored_folderpath, + {'folderpath' => 'scalar'}); + unless (&unescape($env{'form.folderpath'}) =~ m{^(default|supplemental)&}) { + undef($env{'form.folderpath'}); + } } + +# If we are not allowed to make changes, all we can see are supplemental docs if (!$allowed) { - unless($env{'form.folderpath'} =~ /^supplemental/) { - $env{'form.folderpath'} = ''; + unless ($env{'form.folderpath'} =~ /^supplemental/) { + $env{'form.folderpath'} = &supplemental_base(); } } - if (!$env{'form.folderpath'} && $allowed) { - &Apache::loncommon::restore_course_settings('docs_folderpath', - {'pagepath' => 'scalar'}); - } - if ($env{'form.pagepath'}) { - $env{'form.folderpath'}=''; - } +# Make the zeroth entry in supplemental docs page paths, so we can get to top level if ($env{'form.folderpath'} =~ /^supplemental_\d+/) { - $env{'form.folderpath'} = 'supplemental&'. - &escape(&mt('Supplemental '.$crstype.' Documents')).'&'. + $env{'form.folderpath'} = &supplemental_base() + .'&'. $env{'form.folderpath'}; } - &Apache::loncommon::store_course_settings('docs_folderpath', - {'pagepath' => 'scalar', - 'folderpath' => 'scalar'}); - if ($env{'form.folderpath'}) { - my (@folderpath)=split('&',$env{'form.folderpath'}); - $env{'form.foldername'}=&unescape(pop(@folderpath)); - $env{'form.folder'}=pop(@folderpath); - } - if ($env{'form.pagepath'}) { - my (@pagepath)=split('&',$env{'form.pagepath'}); - $env{'form.pagename'}=&unescape(pop(@pagepath)); - $env{'form.folder'}=pop(@pagepath); - $containertag = '<input type="hidden" name="pagepath" value="" />'. - '<input type="hidden" name="pagesymb" value="" />'; - $uploadtag = - '<input type="hidden" name="pagepath" value="'.&HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" />'. - '<input type="hidden" name="pagesymb" value="'.&HTML::Entities::encode($env{'form.pagesymb'},'<>&"').'" />'. - '<input type="hidden" name="folderpath" value="" />'; - } else { - my $folderpath=$env{'form.folderpath'}; - if (!$folderpath) { +# If after all of this, we still don't have any paths, make them + unless ($env{'form.folderpath'}) { + if ($supplementalflag) { + $env{'form.folderpath'}=&supplemental_base(); + } else { + $env{'form.folderpath'}='default&'.&escape(&mt('Main Content'). + ':::::'); + } + } + +# Store this + unless ($toolsflag) { + if ($allowed) { + &Apache::loncommon::store_course_settings($stored_folderpath, + {'folderpath' => 'scalar'}); + } + my $folderpath; + if ($env{'form.folderpath'}) { + $folderpath = $env{'form.folderpath'}; + my (@folders)=split('&',$env{'form.folderpath'}); + $env{'form.foldername'}=&unescape(pop(@folders)); + if ($env{'form.foldername'} =~ /\:1$/) { + $container = 'page'; + } else { + $container = 'sequence'; + } + $env{'form.folder'}=pop(@folders); + } else { if ($env{'form.folder'} eq '' || $env{'form.folder'} eq 'supplemental') { $folderpath='default&'. - &escape(&mt('Main '.$crstype.' Documents')); + &escape(&mt('Main Content').':::::'); } } $containertag = '<input type="hidden" name="folderpath" value="" />'; - $uploadtag = '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($folderpath,'<>&"').'" />'; - } - if ($r->uri=~/^\/adm\/coursedocs\/showdoc\/(.*)$/) { - $showdoc='/'.$1; - } - if ($showdoc) { # got called in sequence from course - $allowed=0; - } else { - if (($env{'form.folder'}=~/^(?:group|default)_/) || - ($env{'form.folder'} =~ m:^\d+/(pages|sequences)/:)) { - $forcestandard = 1; - } - $forcesupplement=($env{'form.folder'}=~/^supplemental_/); - - if ($allowed) { - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['cmd']); - $script=&Apache::lonratedt::editscript('simple'); - } + $pathitem = '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($folderpath,'<>&"').'" />'; + if ($r->uri=~/^\/adm\/coursedocs\/showdoc\/(.*)$/) { + $showdoc='/'.$1; + } + if ($showdoc) { # got called in sequence from course + $allowed=0; + } else { + if ($allowed) { + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['cmd']); + $script=&Apache::lonratedt::editscript('simple'); + } + } } -# subroutine to list form elements -sub create_list_elements { - my @formarr = @_; - my $list = ''; - for my $button (@formarr){ - for my $picture(keys %$button) { - #my $link = Apache::lonhtmlcommon::htmltag('a' ,$button->{$picture}, {href => "test"}); - $list .= Apache::lonhtmlcommon::htmltag('li', $picture.' '.$button->{$picture}, {class => 'LC_menubuttons_inline_text'}); - } - } - return $list; -} - -# subroutine to create ul from list elements -sub create_form_ul { - my $list = shift; - my $ul = Apache::lonhtmlcommon::htmltag('ul',$list, {class => 'LC_ListStyleNormal'}); - return $ul; -} - -# get course data - my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'}; - my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'}; - # get personal data my $uname=$env{'user.name'}; my $udom=$env{'user.domain'}; my $plainname=&escape(&Apache::loncommon::plainname($uname,$udom)); -# graphics settings - - $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL') . "/"); - if ($allowed) { - $script .= &editing_js($udom,$uname); + if ($toolsflag) { + $script .= &inject_data_js(); + my ($home,$other,%outhash)=&authorhosts(); + if (!$home && $other) { + my @hosts; + foreach my $aurole (keys(%outhash)) { + unless(grep(/^\Q$outhash{$aurole}\E/,@hosts)) { + push(@hosts,$outhash{$aurole}); + } + } + $script .= &dump_switchserver_js(@hosts); + } + } else { + my $tid = 1; + my @tabids; + if ($supplementalflag) { + @tabids = ('002','ee2','ff2'); + $tid = 2; + } else { + @tabids = ('aa1','bb1','cc1','ff1'); + unless ($env{'form.folderpath'} =~ /\:1$/) { + unshift(@tabids,'001'); + push(@tabids,('dd1','ee1')); + } + } + my $tabidstr = join("','",@tabids); + $script .= &editing_js($udom,$uname,$supplementalflag). + &history_tab_js(). + &inject_data_js(). + &Apache::lonhtmlcommon::resize_scrollbox_js('docs',$tabidstr,$tid). + &Apache::lonextresedit::extedit_javascript(); + $addentries = { + onload => "javascript:resize_scrollbox('contentscroll','1','1');", + }; + } + $script .= &paste_popup_js(); + my $confirm_switch = &mt("Editing requires switching to the resource's home server.").'\n'. + &mt('Switch server?'); + + } # -------------------------------------------------------------------- Body tag $script = '<script type="text/javascript">'."\n" @@ -2794,29 +4729,33 @@ sub create_form_ul { # Breadcrumbs &Apache::lonhtmlcommon::clear_breadcrumbs(); - if ($allowed) { - &Apache::lonhtmlcommon::add_breadcrumb({ - href=>"/adm/coursedocs",text=>"$crstype Editor"}); - $r->print(&Apache::loncommon::start_page("$crstype Editor", $script, - {'force_register' => $showdoc,}) + if ($showdoc) { + $r->print(&Apache::loncommon::start_page("$crstype documents",undef, + {'force_register' => $showdoc,})); + } elsif ($toolsflag) { + &Apache::lonhtmlcommon::add_breadcrumb({ + href=>"/adm/coursedocs",text=>"$crstype Contents"}); + $r->print(&Apache::loncommon::start_page("$crstype Contents", $script) .&Apache::loncommon::help_open_menu('','',273,'RAT') .&Apache::lonhtmlcommon::breadcrumbs( - 'Editing the Table of Contents for your '.$crstype, + 'Editing Course Contents') + ); + } elsif ($r->uri eq '/adm/supplemental') { + my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype); + $r->print(&Apache::loncommon::start_page("Supplemental $crstype Content",undef, + {'bread_crumbs' => $brcrum,})); + } else { + &Apache::lonhtmlcommon::add_breadcrumb({ + href=>"/adm/coursedocs",text=>"$crstype Contents"}); + $r->print(&Apache::loncommon::start_page("$crstype Contents", $script, + {'add_entries' => $addentries} + ) + .&Apache::loncommon::help_open_menu('','',273,'RAT') + .&Apache::lonhtmlcommon::breadcrumbs( + 'Editing '.$crstype.' Contents', 'Docs_Adding_Course_Doc') ); - } elsif ($showdoc) { - $r->print(&Apache::loncommon::start_page("$crstype documents",undef, - {'force_register' => $showdoc,})); - } else { - my $folder=$env{'form.folder'}; - if ($folder eq '' || $folder eq 'supplemental') { - $env{'form.folderpath'} = 'supplemental&'. - &escape(&mt('Supplemental '.$crstype.' Documents')); - } - my ($breadcrumbtrail) = &breadcrumbs($allowed,$crstype); - $r->print(&Apache::loncommon::start_page("Supplemental documents"). - $breadcrumbtrail); } my %allfiles = (); @@ -2829,7 +4768,7 @@ sub create_form_ul { # Process file upload - phase one - upload and parse primary file. undef($hadchanges); $uploadphase = &process_file_upload(\$upload_output,$coursenum,$coursedom, - \%allfiles,\%codebase,$context); + \%allfiles,\%codebase,$context,$crstype); if ($hadchanges) { &mark_hash_old(); } @@ -2856,52 +4795,65 @@ sub create_form_ul { my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'}; my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'}; my ($destination,$dir_root) = &embedded_destination(); - $r->print(&Apache::loncommon::modify_html_refs('coursedoc',$destination, - $docuname,$docudom,undef, - $dir_root). - &return_to_editor()); + my $result = + &Apache::loncommon::modify_html_refs('coursedoc',$destination, + $docuname,$docudom,undef, + $dir_root); + $r->print($result.&return_to_editor()); + } elsif ($env{'form.phase'} eq 'decompress_uploaded') { + $uploadphase = 'decompress_phase_one'; + $r->print(&decompression_phase_one(). + &return_to_editor()); + } elsif ($env{'form.phase'} eq 'decompress_cleanup') { + $uploadphase = 'decompress_phase_two'; + $r->print(&decompression_phase_two(). + &return_to_editor()); } } - unless ($showdoc || $uploadphase) { + if ($allowed && $toolsflag) { + $r->print(&startContentScreen('tools')); + $r->print(&generate_admin_menu($crstype)); + $r->print(&endContentScreen()); + } elsif ((!$showdoc) && (!$uploadphase)) { # ----------------------------------------------------------------------------- my %lt=&Apache::lonlocal::texthash( - 'uplm' => 'Upload a new main '.lc($crstype).' document', - 'upls' => 'Upload a new supplemental '.lc($crstype).' document', - 'impp' => 'Import a document', 'copm' => 'All documents out of a published map into this folder', - 'upld' => 'Import Document', + 'upfi' => 'Upload File', + 'upld' => 'Upload Content', 'srch' => 'Search', 'impo' => 'Import', - 'wish' => 'Import from Wishlist', + 'lnks' => 'Import from Stored Links', + 'impm' => 'Import from Assembled Map', 'selm' => 'Select Map', 'load' => 'Load Map', - 'reco' => 'Recover Deleted Documents', 'newf' => 'New Folder', 'newp' => 'New Composite Page', - 'extr' => 'External Resource', 'syll' => 'Syllabus', 'navc' => 'Table of Contents', 'sipa' => 'Simple Course Page', 'sipr' => 'Simple Problem', + 'webp' => 'Blank Web Page (editable)', 'drbx' => 'Drop Box', - 'scuf' => 'Score Upload Form', + 'scuf' => 'External Scores (handgrade, upload, clicker)', 'bull' => 'Discussion Board', 'mypi' => 'My Personal Information Page', 'grpo' => 'Group Portfolio', 'rost' => 'Course Roster', - 'abou' => 'Personal Information Page for a User', - 'imsf' => 'IMS Import', - 'imsl' => 'Import IMS package', + 'abou' => 'Personal Information Page for a User', + 'imsf' => 'IMS Upload', + 'imsl' => 'Upload IMS package', + 'cms' => 'Origin of IMS package', + 'se' => 'Select', 'file' => 'File', 'title' => 'Title', 'comment' => 'Comment', 'parse' => 'Upload embedded images/multimedia files if HTML file', - 'nd' => 'Upload Document', - 'pm' => 'Published Map', - 'sd' => 'Special Document', - 'mo' => 'More Options', - ); + 'bb5' => 'Blackboard 5', + 'bb6' => 'Blackboard 6', + 'angel5' => 'ANGEL 5.5', + 'webctce4' => 'WebCT 4 Campus Edition', + ); # ----------------------------------------------------------------------------- my $fileupload=(<<FIUP); $lt{'file'}:<br /> @@ -2916,69 +4868,94 @@ FIUP <input type="checkbox" name="parserflag" checked="checked" /> $lt{'parse'} </label> CHBO + my $imsfolder = $env{'form.folder'}; + if ($imsfolder eq '') { + $imsfolder = 'default'; + } + my $imspform=(<<IMSFORM); + <a class="LC_menubuttons_link" href="javascript:toggleUpload('ims');"> + $lt{'imsf'}</a> $help{'Importing_IMS_Course'} + <form name="uploadims" action="/adm/imsimportdocs" method="post" enctype="multipart/form-data" target="IMSimport"> + <fieldset id="uploadimsform" style="display: none;"> + <legend>$lt{'imsf'}</legend> + $fileupload + <br /> + <p> + $lt{'cms'}: + <select name="source"> + <option value="-1" selected="selected">$lt{'se'}</option> + <option value="bb5">$lt{'bb5'}</option> + <option value="bb6">$lt{'bb6'}</option> + <option value="angel5">$lt{'angel5'}</option> + <option value="webctce4">$lt{'webctce4'}</option> + </select> + <input type="hidden" name="folder" value="$imsfolder" /> + </p> + <input type="hidden" name="phase" value="one" /> + <input type="button" value="$lt{'imsl'}" onclick="makeims(this.form);" /> + </fieldset> + </form> +IMSFORM - my $fileuploada = "<input type='submit' value='".$lt{'upld'}."' /> $help{'Uploading_From_Harddrive'}"; my $fileuploadform=(<<FUFORM); - <form name="uploaddocument" action="/adm/coursedocs" method="post" enctype="multipart/form-data"> + <a class="LC_menubuttons_link" href="javascript:toggleUpload('doc');"> + $lt{'upfi'}</a> $help{'Uploading_From_Harddrive'} + <form name="uploaddocument" action="/adm/coursedocs" method="post" enctype="multipart/form-data"> + <fieldset id="uploaddocform" style="display: none;"> + <legend>$lt{'upfi'}</legend> <input type="hidden" name="active" value="aa" /> $fileupload <br /> $lt{'title'}:<br /> - <input type="text" size="80" name="comment" /> - $uploadtag + <input type="text" size="60" name="comment" /> + $pathitem <input type="hidden" name="cmd" value="upload_default" /> <br /> - <span class="LC_nobreak"> + <span class="LC_nobreak" style="float:left"> $checkbox </span> -FUFORM - #$list .= Apache::lonhtmlcommon::htmltag('li', $picture.' '.$button->{$picture}, {class => 'LC_menubuttons_inline_text'}); - #$fileuploadform .= create_form_ul(create_list_elements(@fileuploada)); - $fileuploadform .= create_form_ul(Apache::lonhtmlcommon::htmltag('li',$fileuploada,{class => 'LC_menubuttons_inline_text'})); - $fileuploadform .= (<<FUFORM); - </form> + <br clear="all" /> + <input type="submit" value="$lt{'upld'}" /> + </fieldset> + </form> FUFORM - my $simpleeditdefaultform=(<<SEDFFORM); - <form action="/adm/coursedocs" method="post" name="simpleeditdefault"> + my $importpubform=(<<SEDFFORM); + <a class="LC_menubuttons_link" href="javascript:toggleMap('map');"> + $lt{'impm'}</a>$help{'Load_Map'} + <form action="/adm/coursedocs" method="post" name="mapimportform"> + <fieldset id="importmapform" style="display: none;"> + <legend>$lt{'impm'}</legend> <input type="hidden" name="active" value="bb" /> + $lt{'copm'}<br /> + <span class="LC_nobreak"> + <input type="text" name="importmap" size="40" value="" + onfocus="this.blur();openbrowser('mapimportform','importmap','sequence,page','');" /> + <a href="javascript:openbrowser('mapimportform','importmap','sequence,page','');">$lt{'selm'}</a></span><br /> + <input type="submit" name="loadmap" value="$lt{'load'}" /> + </fieldset> + </form> + SEDFFORM - my @simpleeditdefaultforma = ( - { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/src.png" alt="'.$lt{srch}.'" onclick="javascript:groupsearch()" />' => "$uploadtag<a class='LC_menubuttons_link' href='javascript:groupsearch()'>$lt{'srch'}</a>" }, + my @importpubforma = ( + { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/src.png" alt="'.$lt{srch}.'" onclick="javascript:groupsearch()" />' => $pathitem."<a class='LC_menubuttons_link' href='javascript:groupsearch()'>$lt{'srch'}</a>" }, { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/res.png" alt="'.$lt{impo}.'" onclick="javascript:groupimport();"/>' => "<a class='LC_menubuttons_link' href='javascript:groupimport();'>$lt{'impo'}</a>$help{'Importing_LON-CAPA_Resource'}" }, - { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/wishlist.png" alt="'.$lt{wish}.'" onclick="javascript:open_Wishlist_Import();" />' => "<a class='LC_menubuttons_link' href='javascript:open_Wishlist_Import();'>$lt{'wish'}</a>" }, + { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/wishlist.png" alt="'.$lt{lnks}.'" onclick="javascript:open_StoredLinks_Import();" />' => "<a class='LC_menubuttons_link' href='javascript:open_StoredLinks_Import();'>$lt{'lnks'}</a>" }, + { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/sequence.png" alt="'.$lt{impm}.'" onclick="javascript:toggleMap(\'map\');" />' => $importpubform } ); - $simpleeditdefaultform .= create_form_ul(create_list_elements(@simpleeditdefaultforma)); - $simpleeditdefaultform .=(<<SEDFFORM); - <hr /> - <p> - $lt{'copm'}<br /> - <input type="text" size="40" name="importmap" /><br /> - <span class="LC_nobreak"><input type="button" - onclick="javascript:openbrowser('simpleeditdefault','importmap','sequence,page','')" - value="$lt{'selm'}" /> <input type="submit" name="loadmap" value="$lt{'load'}" /> - $help{'Load_Map'}</span> - </p> - </form> -SEDFFORM - - my $extresourcesform=(<<ERFORM); - <form action="/adm/coursedocs" method="post" name="newext"> - $uploadtag - <input type="hidden" name="importdetail" value="" /> - <a class="LC_menubuttons_link" href="javascript:makenewext('newext');">$lt{'extr'}</a>$help{'Adding_External_Resource'} - </form> -ERFORM - + $importpubform = &create_form_ul(&create_list_elements(@importpubforma)); + my $extresourcesform = + &Apache::lonextresedit::extedit_form(0,0,undef,undef,$pathitem, + $help{'Adding_External_Resource'}); if ($allowed) { - &update_paste_buffer($coursenum,$coursedom); - my %lt=&Apache::lonlocal::texthash( - 'vc' => 'Verify Content', - 'cv' => 'Check/Set Resource Versions', - 'ls' => 'List Symbs', - 'sl' => 'Show Log' - ); - + my $folder = $env{'form.folder'}; + if ($folder eq '') { + $folder='default'; + } + my $output = &update_paste_buffer($coursenum,$coursedom,$folder); + if ($output) { + $r->print($output); + } $r->print(<<HIDDENFORM); <form name="renameform" method="post" action="/adm/coursedocs"> <input type="hidden" name="title" /> @@ -2987,64 +4964,38 @@ ERFORM <input type="hidden" name="copyfolder" /> $containertag </form> - <form name="simpleedit" method="post" action="/adm/coursedocs"> - <input type="hidden" name="importdetail" value="" /> - $uploadtag - </form> + HIDDENFORM + $r->print(&makesimpleeditform($pathitem)."\n". + &makedocslogform($pathitem."\n". + '<input type="hidden" name="folder" value="'. + $env{'form.folder'}.'" />'."\n")); } -# --------------------------------------------------------- Main tab structure - - my $activeClass = 1; - my $active = ''; - my %tabtitles = ( - main => { - Course => &mt('Main Course Documents'), - Community => &mt('Main Community Documents'), - }, - supplemental => { - Course => &mt('Supplemental Course Documents'), - Community => &mt('Supplemental Community Documents'), - }, - ); + +# Generate the tabs + my ($mode,$needs_end); + if (($supplementalflag) && (!$allowed)) { + my @folders = split('&',$env{'form.folderpath'}); + unless (@folders > 2) { + &Apache::lonnavdisplay::startContentScreen($r,'supplemental'); + $needs_end = 1; + } + } else { + $r->print(&startContentScreen(($supplementalflag?'suppdocs':'docs'))); + $needs_end = 1; + } + +# + + my $savefolderpath; + if ($allowed) { - $r->print('<ul class="LC_TabContentBigger" id="mainnav">'); - if (($standard) && ($allowed) && (!$forcesupplement) && (($env{'form.folderpath'}=~/^default/) || $env{'form.folderpath'}eq"" || ($env{'form.pagepath'}))) { - if($activeClass == 1){ - $active = 'class="active"'; - $activeClass = 0; - } - } - $r->print('<li '.$active - . ' onclick="javascript:showPage(this,\'mainCourseDocuments\',\'mainnav\',\'maincoursedoc\');"><a href="#"><b>'.$tabtitles{'main'}{$crstype}.'</b></a></li>'); - $active = ''; - if (!$forcestandard || ($env{'form.folderpath'}=~/^supplemental/)) { - if($activeClass == 1){ - $active = 'class="active"'; - } - } - $r->print('<li '.$active - .' onclick="javascript:showPage(this,\'supplCourseDocuments\',\'mainnav\',\'maincoursedoc\');"><a href="#"><b>'.$tabtitles{'supplemental'}{$crstype}.'</b></a></li>'); - $r->print('</ul>'); - } else { - $r->print('<br />'); - } - $r->print('<div class="LC_Box" style="clear:both;margin:0;">' - .'<div id="maincoursedoc" style="margin:0 0;padding:0 0;">'); -# --------------------------------------------------------- Standard documents - my $savefolderpath; - $active = 'style="display: none;"'; - if($activeClass == 0){ - $active = 'style="display: block;"'; - } - if ($allowed) { - $r->print('<div class="LC_ContentBox" id="mainCourseDocuments" '.$active.'>'); my $folder=$env{'form.folder'}; - if ($folder eq '' || $folder=~/^supplemental/) { + if ($folder eq '' || $supplementalflag) { $folder='default'; $savefolderpath = $env{'form.folderpath'}; - $env{'form.folderpath'}='default&'.&escape($tabtitles{'main'}{$crstype}); - $uploadtag = '<input type="hidden" name="folderpath" value="'. + $env{'form.folderpath'}='default&'.&escape(&mt('Main Content')); + $pathitem = '<input type="hidden" name="folderpath" value="'. &HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />'; } my $postexec=''; @@ -3058,35 +5009,14 @@ HIDDENFORM } else { #$postexec='self.close();'; } - my $folderseq='/uploaded/'.$coursedom.'/'.$coursenum.'/default_'.time. - '.sequence'; - my $pageseq = '/uploaded/'.$coursedom.'/'.$coursenum.'/default_'.time. - '.page'; - my $container='sequence'; - if ($env{'form.pagepath'}) { - $container='page'; - } + my $folderseq='/uploaded/'.$coursedom.'/'.$coursenum.'/default_new.sequence'; + my $pageseq = '/uploaded/'.$coursedom.'/'.$coursenum.'/default_new.page'; my $readfile='/uploaded/'.$coursedom.'/'.$coursenum.'/'.$folder.'.'.$container; - - - my $recoverform=(<<RFORM); - <form action="/adm/groupsort" method="post" name="recover"> - <a class="LC_menubuttons_link" href="javascript:groupopen('$readfile',1)">$lt{'reco'}</a> - </form> -RFORM - - my $imspform=(<<IMSPFORM); - <form action="/adm/imsimportdocs" method="post" name="ims"> - <input type="hidden" name="folder" value="$folder" /> - <a class="LC_menubuttons_link" href="javascript:makeims();">$lt{'imsf'}</a> - </form> -IMSPFORM - my $newnavform=(<<NNFORM); <form action="/adm/coursedocs" method="post" name="newnav"> - <input type="hidden" name="active" value="cc" /> - $uploadtag + <input type="hidden" name="active" value="ee" /> + $pathitem <input type="hidden" name="importdetail" value="$lt{'navc'}=/adm/navmaps" /> <a class="LC_menubuttons_link" href="javascript:document.newnav.submit()">$lt{'navc'}</a> @@ -3095,8 +5025,8 @@ IMSPFORM NNFORM my $newsmppageform=(<<NSPFORM); <form action="/adm/coursedocs" method="post" name="newsmppg"> - <input type="hidden" name="active" value="cc" /> - $uploadtag + <input type="hidden" name="active" value="ee" /> + $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makesmppage();"> $lt{'sipa'}</a> $help{'Simple Page'} @@ -3106,10 +5036,10 @@ NSPFORM my $newsmpproblemform=(<<NSPROBFORM); <form action="/adm/coursedocs" method="post" name="newsmpproblem"> <input type="hidden" name="active" value="cc" /> - $uploadtag + $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makesmpproblem();">$lt{'sipr'}</a> - $help{'Simple Problem'} + $help{'Simple_Problem'} </form> NSPROBFORM @@ -3117,16 +5047,17 @@ NSPROBFORM my $newdropboxform=(<<NDBFORM); <form action="/adm/coursedocs" method="post" name="newdropbox"> <input type="hidden" name="active" value="cc" /> - $uploadtag + $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makedropbox();">$lt{'drbx'}</a> + $help{'Dropbox'} </form> NDBFORM my $newexuploadform=(<<NEXUFORM); <form action="/adm/coursedocs" method="post" name="newexamupload"> <input type="hidden" name="active" value="cc" /> - $uploadtag + $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makeexamupload();">$lt{'scuf'}</a> $help{'Score_Upload_Form'} @@ -3135,8 +5066,8 @@ NEXUFORM my $newbulform=(<<NBFORM); <form action="/adm/coursedocs" method="post" name="newbul"> - <input type="hidden" name="active" value="cc" /> - $uploadtag + <input type="hidden" name="active" value="dd" /> + $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makebulboard();" >$lt{'bull'}</a> $help{'Bulletin Board'} @@ -3145,8 +5076,8 @@ NBFORM my $newaboutmeform=(<<NAMFORM); <form action="/adm/coursedocs" method="post" name="newaboutme"> - <input type="hidden" name="active" value="cc" /> - $uploadtag + <input type="hidden" name="active" value="dd" /> + $pathitem <input type="hidden" name="importdetail" value="$plainname=/adm/$udom/$uname/aboutme" /> <a class="LC_menubuttons_link" href="javascript:document.newaboutme.submit()">$lt{'mypi'}</a> @@ -3156,38 +5087,61 @@ NAMFORM my $newaboutsomeoneform=(<<NASOFORM); <form action="/adm/coursedocs" method="post" name="newaboutsomeone"> - <input type="hidden" name="active" value="cc" /> - $uploadtag + <input type="hidden" name="active" value="dd" /> + $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makeabout();">$lt{'abou'}</a> </form> NASOFORM - my $newrosterform=(<<NROSTFORM); <form action="/adm/coursedocs" method="post" name="newroster"> - <input type="hidden" name="active" value="cc" /> - $uploadtag + <input type="hidden" name="active" value="dd" /> + $pathitem <input type="hidden" name="importdetail" value="$lt{'rost'}=/adm/viewclasslist" /> <a class="LC_menubuttons_link" href="javascript:document.newroster.submit()">$lt{'rost'}</a> - $help{'Course Roster'} + $help{'Course_Roster'} </form> NROSTFORM + my $newwebpage; + if ($folder =~ /^default_?(\d*)$/) { + $newwebpage = "/uploaded/$coursedom/$coursenum/docs/"; + if ($1) { + $newwebpage .= $1; + } else { + $newwebpage .= 'default'; + } + $newwebpage .= '/new.html'; + } + my $newwebpageform =(<<NWEBFORM); + <form action="/adm/coursedocs" method="post" name="newwebpage"> + <input type="hidden" name="active" value="ee" /> + $pathitem + <input type="hidden" name="importdetail" value="$newwebpage" /> + <a class="LC_menubuttons_link" href="javascript:makewebpage();">$lt{'webp'}</a> + $help{'Web_Page'} + </form> +NWEBFORM + + my $specialdocumentsform; my @specialdocumentsforma; +my $gradingform; +my @gradingforma; +my $communityform; +my @communityforma; my $newfolderform; my $newfolderb; - unless ($env{'form.pagepath'}) { - my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); + my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); my $newpageform=(<<NPFORM); <form action="/adm/coursedocs" method="post" name="newpage"> <input type="hidden" name="folderpath" value="$path" /> <input type="hidden" name="importdetail" value="" /> - <input type="hidden" name="active" value="cc" /> + <input type="hidden" name="active" value="ee" /> <a class="LC_menubuttons_link" href="javascript:makenewpage(document.newpage,'$pageseq');">$lt{'newp'}</a> $help{'Adding_Pages'} </form> @@ -3196,17 +5150,17 @@ NPFORM $newfolderform=(<<NFFORM); <form action="/adm/coursedocs" method="post" name="newfolder"> - <input type="hidden" name="folderpath" value="$path" /> + $pathitem <input type="hidden" name="importdetail" value="" /> - <input type="hidden" name="active" value="aa" /> + <input type="hidden" name="active" value="" /> <a href="javascript:makenewfolder(document.newfolder,'$folderseq');">$lt{'newf'}</a>$help{'Adding_Folders'} </form> NFFORM my $newsylform=(<<NSYLFORM); <form action="/adm/coursedocs" method="post" name="newsyl"> - <input type="hidden" name="active" value="cc" /> - $uploadtag + <input type="hidden" name="active" value="ee" /> + $pathitem <input type="hidden" name="importdetail" value="$lt{'syll'}=/public/$coursedom/$coursenum/syllabus" /> <a class="LC_menubuttons_link" href="javascript:document.newsyl.submit()">$lt{'syll'}</a> @@ -3217,8 +5171,8 @@ NSYLFORM my $newgroupfileform=(<<NGFFORM); <form action="/adm/coursedocs" method="post" name="newgroupfiles"> - <input type="hidden" name="active" value="cc" /> - $uploadtag + <input type="hidden" name="active" value="dd" /> + $pathitem <input type="hidden" name="importdetail" value="$lt{'grpo'}=/adm/$coursedom/$coursenum/aboutme" /> <a class="LC_menubuttons_link" href="javascript:document.newgroupfiles.submit()">$lt{'grpo'}</a> @@ -3228,95 +5182,93 @@ NGFFORM @specialdocumentsforma=( {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/page.png" alt="'.$lt{newp}.'" onclick="javascript:makenewpage(document.newpage,\''.$pageseq.'\');" />'=>$newpageform}, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/syllabus.png" alt="'.$lt{syll}.'" onclick="document.newsyl.submit()" />'=>$newsylform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/groupportfolio.png" alt="'.$lt{grpo}.'" onclick="document.newgroupfiles.submit()" />'=>$newgroupfileform}, - ); + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/navigation.png" alt="'.$lt{navc}.'" onclick="document.newnav.submit()" />'=>$newnavform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simple.png" alt="'.$lt{sipa}.'" onclick="javascript:makesmppage();" />'=>$newsmppageform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/webpage.png" alt="'.$lt{webp}.'" onclick="javascript:makewebpage();" />'=>$newwebpageform}, + ); + $specialdocumentsform = &create_form_ul(&create_list_elements(@specialdocumentsforma)); + my @importdoc = ( - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:makenewext(\'newext\');" />'=>$extresourcesform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/ims.png" alt="'.$lt{imsf}.'" onclick="javascript:makeims();" />'=>$imspform},); - $fileuploadform = create_form_ul(create_list_elements(@importdoc)) . '<hr/>' . $fileuploadform; - - push @specialdocumentsforma, ({'<img class="LC_noBorder LC_middle" src="/res/adm/pages/navigation.png" alt="'.$lt{navc}.'" onclick="document.newnav.submit()" />'=>$newnavform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simple.png" alt="'.$lt{sipa}.'" onclick="javascript:makesmppage();" />'=>$newsmppageform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{sipr}.'" onclick="javascript:makesmpproblem();" />'=>$newsmpproblemform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/dropbox.png" alt="'.$lt{drbx}.'" onclick="javascript:makedropbox();" />'=>$newdropboxform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/scoreupfrm.png" alt="'.$lt{scuf}.'" onclick="javascript:makeexamupload();" />'=>$newexuploadform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/bchat.png" alt="'.$lt{bull}.'" onclick="javascript:makebulboard();" />'=>$newbulform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/myaboutme.png" alt="'.$lt{mypi}.'" onclick="javascript:makebulboard();" />'=>$newaboutmeform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/aboutme.png" alt="'.$lt{abou}.'" onclick="javascript:makeabout();" />'=>$newaboutsomeoneform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/clst.png" alt="'.$lt{rost}.'" onclick="document.newroster.submit()" />'=>$newrosterform},); + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="toggleUpload(\'ext\');" />'=>$extresourcesform} + ); + unless ($container eq 'page') { + push(@importdoc, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/ims.png" alt="'.$lt{imsf}.'" onclick="javascript:toggleUpload(\'ims\');" />'=>$imspform} + ); + } + push(@importdoc, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/pdfupload.png" alt="'.$lt{upl}.'" onclick="javascript:toggleUpload(\'doc\');" />'=>$fileuploadform} + ); + $fileuploadform = &create_form_ul(&create_list_elements(@importdoc)); - $specialdocumentsform = create_form_ul(create_list_elements(@specialdocumentsforma)); - } + @gradingforma=( + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{sipr}.'" onclick="javascript:makesmpproblem();" />'=>$newsmpproblemform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/dropbox.png" alt="'.$lt{drbx}.'" onclick="javascript:makedropbox();" />'=>$newdropboxform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/scoreupfrm.png" alt="'.$lt{scuf}.'" onclick="javascript:makeexamupload();" />'=>$newexuploadform}, -if($env{'form.pagepath'}) { - - @specialdocumentsforma=( - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.&mt('Simple Problem').'" onclick="javascript:makesmpproblem();" />'=>$newsmpproblemform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/scoreupfrm.png" alt="'.&mt('Score Upload Form').'" onclick="javascript:makeexamupload();" />'=>$newexuploadform} - ); - $specialdocumentsform= create_form_ul(create_list_elements(@specialdocumentsforma)); -} + ); + $gradingform = &create_form_ul(&create_list_elements(@gradingforma)); -my @tools = ( -# {'<img class="LC_noBorder LC_middle" align="left" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" />'=>$extresourcesform}, -# {'<img class="LC_noBorder LC_middle" align="left" src="/res/adm/pages/ims.png" alt="'.$lt{imsf}.'" />'=>$imspform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/recover.png" alt="'.$lt{reco}.'" onclick="javascript:groupopen(\''.$readfile.'\',1)" />'=>$recoverform}, - ); + @communityforma=( + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/bchat.png" alt="'.$lt{bull}.'" onclick="javascript:makebulboard();" />'=>$newbulform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/myaboutme.png" alt="'.$lt{mypi}.'" onclick="javascript:makebulboard();" />'=>$newaboutmeform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/aboutme.png" alt="'.$lt{abou}.'" onclick="javascript:makeabout();" />'=>$newaboutsomeoneform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/clst.png" alt="'.$lt{rost}.'" onclick="document.newroster.submit()" />'=>$newrosterform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/groupportfolio.png" alt="'.$lt{grpo}.'" onclick="document.newgroupfiles.submit()" />'=>$newgroupfileform}, + ); + $communityform = &create_form_ul(&create_list_elements(@communityforma)); my %orderhash = ( - 'aa' => ['Import Documents',$fileuploadform], - 'bb' => ['Published Resources',$simpleeditdefaultform], - 'cc' => ['Special Documents',$specialdocumentsform], - 'dd' => ['Tools', create_form_ul(create_list_elements(@tools)).&generate_admin_options(\%help,\%env)], + 'aa' => ['Upload',$fileuploadform], + 'bb' => ['Import',$importpubform], + 'cc' => ['Grading',$gradingform], ); -unless($env{'form.pagepath'}) { +unless ($container eq 'page') { $orderhash{'00'} = ['Newfolder',$newfolderform]; + $orderhash{'dd'} = ['Collaboration',$communityform]; + $orderhash{'ee'} = ['Other',$specialdocumentsform]; } -my $tid='1'; $hadchanges=0; - my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype); - if ($error) { - $r->print('<p><span class="LC_error">'.$error.'</span></p>'); - } - if ($hadchanges) { - &mark_hash_old(); - } + unless (($supplementalflag || $toolsflag)) { + my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype, + $supplementalflag,\%orderhash,$iconpath,$pathitem); + if ($error) { + $r->print('<p><span class="LC_error">'.$error.'</span></p>'); + } + if ($hadchanges) { + &mark_hash_old(); + } - &changewarning($r,''); -$r->print(&generate_edit_table($tid,\%orderhash)); + &changewarning($r,''); + } + } + +# Supplemental documents start here -$r->print('</div>'); - } -# ----------------------------------------------------- Supplemental documents - $active = 'style="display: none;"'; - if($activeClass == 1){ - $active = 'style="display: block;"'; - } - $r->print('<div class="LC_ContentBox" id="supplCourseDocuments" '.$active.'>'); my $folder=$env{'form.folder'}; - unless ($folder=~/^supplemental/) { + unless ($supplementalflag) { $folder='supplemental'; } if ($folder =~ /^supplemental$/ && (($env{'form.folderpath'} =~ /^default\&/) || ($env{'form.folderpath'} eq ''))) { - $env{'form.folderpath'} = 'supplemental&'. - &escape(&mt('Supplemental '.$crstype.' Documents')); + $env{'form.folderpath'} = &supplemental_base(); } elsif ($allowed) { $env{'form.folderpath'} = $savefolderpath; } - $env{'form.pagepath'} = ''; + $pathitem = '<input type="hidden" name="folderpath" value="'. + &HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />'; if ($allowed) { my $folderseq= - '/uploaded/'.$coursedom.'/'.$coursenum.'/supplemental_'.time. - '.sequence'; - - my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); + '/uploaded/'.$coursedom.'/'.$coursenum.'/supplemental_new.sequence'; - my $supupdocformbtn = "<input type='submit' value='".$lt{'upld'}."' />$help{'Uploading_From_Harddrive'}"; my $supupdocform=(<<SUPDOCFORM); + <a class="LC_menubuttons_link" href="javascript:toggleUpload('suppdoc');"> + $lt{'upfi'}</a> $help{'Uploading_From_Harddrive'} <form action="/adm/coursedocs" method="post" name="supuploaddocument" enctype="multipart/form-data"> + <fieldset id="uploadsuppdocform" style="display: none;"> + <legend>$lt{'upfi'}</legend> <input type="hidden" name="active" value="ee" /> $fileupload <br /> @@ -3328,35 +5280,30 @@ $r->print('</div>'); $lt{'comment'}:<br /> <textarea cols="50" rows="4" name="comment"></textarea> <br /> - <input type="hidden" name="folderpath" value="$path" /> + $pathitem <input type="hidden" name="cmd" value="upload_supplemental" /> + <input type='submit' value="$lt{'upld'}" /> + </form> SUPDOCFORM - $supupdocform .= create_form_ul(Apache::lonhtmlcommon::htmltag('li',$supupdocformbtn,{class => 'LC_menubuttons_inline_text'}))."</form>"; my $supnewfolderform=(<<SNFFORM); <form action="/adm/coursedocs" method="post" name="supnewfolder"> - <input type="hidden" name="active" value="ee" /> - <input type="hidden" name="folderpath" value="$path" /> + <input type="hidden" name="active" value="" /> + $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makenewfolder(document.supnewfolder,'$folderseq');">$lt{'newf'}</a> $help{'Adding_Folders'} </form> SNFFORM - - my $supnewextform=(<<SNEFORM); - <form action="/adm/coursedocs" method="post" name="supnewext"> - <input type="hidden" name="active" value="ff" /> - <input type="hidden" name="folderpath" value="$path" /> - <input type="hidden" name="importdetail" value="" /> - <a class="LC_menubuttons_link" href="javascript:makenewext('supnewext');">$lt{'extr'}</a> $help{'Adding_External_Resource'} - </form> -SNEFORM + my $supextform = + &Apache::lonextresedit::extedit_form(1,0,undef,undef,$pathitem, + $help{'Adding_External_Resource'}); my $supnewsylform=(<<SNSFORM); <form action="/adm/coursedocs" method="post" name="supnewsyl"> <input type="hidden" name="active" value="ff" /> - <input type="hidden" name="folderpath" value="$path" /> + $pathitem <input type="hidden" name="importdetail" value="Syllabus=/public/$coursedom/$coursenum/syllabus" /> <a class="LC_menubuttons_link" href="javascript:document.supnewsyl.submit()">$lt{'syll'}</a> @@ -3367,7 +5314,7 @@ SNSFORM my $supnewaboutmeform=(<<SNAMFORM); <form action="/adm/coursedocs" method="post" name="supnewaboutme"> <input type="hidden" name="active" value="ff" /> - <input type="hidden" name="folderpath" value="$path" /> + $pathitem <input type="hidden" name="importdetail" value="$plainname=/adm/$udom/$uname/aboutme" /> <a class="LC_menubuttons_link" href="javascript:document.supnewaboutme.submit()">$lt{'mypi'}</a> @@ -3375,41 +5322,79 @@ SNSFORM </form> SNAMFORM + my $supwebpage; + if ($folder =~ /^supplemental_?(\d*)$/) { + $supwebpage = "/uploaded/$coursedom/$coursenum/supplemental/"; + if ($1) { + $supwebpage .= $1; + } else { + $supwebpage .= 'default'; + } + $supwebpage .= '/new.html'; + } + my $supwebpageform =(<<SWEBFORM); + <form action="/adm/coursedocs" method="post" name="supwebpage"> + <input type="hidden" name="active" value="cc" /> + $pathitem + <input type="hidden" name="importdetail" value="$supwebpage" /> + <a class="LC_menubuttons_link" href="javascript:makewebpage('supp');">$lt{'webp'}</a> + $help{'Web_Page'} + </form> +SWEBFORM + my @specialdocs = ( {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/syllabus.png" alt="'.$lt{syll}.'" onclick="document.supnewsyl.submit()" />' =>$supnewsylform}, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/myaboutme.png" alt="'.$lt{mypi}.'" onclick="document.supnewaboutme.submit()" />' =>$supnewaboutmeform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/webpage.png" alt="'.$lt{webp}.'" onclick="javascript:makewebpage('."'supp'".');" />'=>$supwebpageform}, + ); my @supimportdoc = ( - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:makenewext(\'supnewext\');" />' - =>$supnewextform}, - ); -$supupdocform = create_form_ul(create_list_elements(@supimportdoc)) . '<hr/>' . $supupdocform; + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:toggleUpload(\'suppext\')" />' + =>$supextform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/pdfupload.png" alt="'.$lt{upl}.'" onclick="javascript:toggleUpload(\'suppdoc\');" />' + =>$supupdocform}, + ); + +$supupdocform = &create_form_ul(&create_list_elements(@supimportdoc)); my %suporderhash = ( '00' => ['Supnewfolder', $supnewfolderform], - 'ee' => ['Import Documents',$supupdocform], - 'ff' => ['Special Documents',create_form_ul(create_list_elements(@specialdocs))] + 'ee' => ['Upload',$supupdocform], + 'ff' => ['Other',&create_form_ul(&create_list_elements(@specialdocs))] ); - - my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype); - if ($error) { - $r->print('<p><span class="LC_error">'.$error.'</span></p>'); - } - my $tid='2'; - $r->print(&generate_edit_table($tid,\%suporderhash)); - } else { - my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype); + if ($supplementalflag) { + my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype, + $supplementalflag,\%suporderhash,$iconpath,$pathitem); + if ($error) { + $r->print('<p><span class="LC_error">'.$error.'</span></p>'); + } else { + if ($suppchanges) { + my %servers = &Apache::lonnet::internet_dom_servers($coursedom); + my @ids=&Apache::lonnet::current_machine_ids(); + foreach my $server (keys(%servers)) { + next if (grep(/^\Q$server\E$/,@ids)); + my $hashid=$coursenum.':'.$coursedom; + my $cachekey = &escape('suppcount').':'.&escape($hashid); + &Apache::lonnet::remote_devalidate_cache($server,[$cachekey]); + } + &Apache::lonnet::get_numsuppfiles($coursenum,$coursedom,1); + undef($suppchanges); + } + } + } + } elsif ($supplementalflag) { + my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype, + $supplementalflag,'',$iconpath,$pathitem); if ($error) { $r->print('<p><span class="LC_error">'.$error.'</span></p>'); } } - -$r->print('</div>'); -$r->print('</div></div>'); - + if ($needs_end) { + $r->print(&endContentScreen()); + } if ($allowed) { $r->print(' @@ -3420,14 +5405,12 @@ $r->print('</div></div>'); <input type="hidden" name="residx" /> </form>'); } - } else { - unless ($uploadphase) { + } elsif ($showdoc) { # -------------------------------------------------------- This is showdoc mode - $r->print("<h1>".&mt('Uploaded Document').' - '. - &Apache::lonnet::gettitle($r->uri).'</h1><p>'. + $r->print("<h1>".&mt('Uploaded Document').' - '. + &Apache::lonnet::gettitle($r->uri).'</h1><p class="LC_warning">'. &mt('It is recommended that you use an up-to-date virus scanner before handling this file.')."</p><table>". - &entryline(0,&mt("Click to download or use your browser's Save Link function"),$showdoc).'</table>'); - } + &entryline(0,&mt("Click to download or use your browser's Save Link function"),$showdoc).'</table>'); } } $r->print(&Apache::loncommon::end_page()); @@ -3470,100 +5453,319 @@ sub return_to_editor { '</a></p>'; } -sub generate_admin_options { - my ($help_ref,$env_ref) = @_; - my %lt=&Apache::lonlocal::texthash( - 'vc' => 'Verify Content', - 'cv' => 'Check/Set Resource Versions', - 'ls' => 'List Symbs', - 'sl' => 'Show Log', - 'imse' => 'IMS Export', - 'dcd' => 'Dump Course Documents to Construction Space: available on other servers' - ); - my %help = %{$help_ref}; - my %env = %{$env_ref}; - my $dumpbut=&dumpbutton(); - my $exportbut=&exportbutton(); - my @list = ( - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/verify.png" alt="'.$lt{vc}.'" onclick=\'javascript:injectData(document.courseverify, "dummy", "verify", "'.$lt{'vc'}.'")\' />' - => "<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"verify\", \"$lt{'vc'}\")'>$lt{'vc'}</a>$help{'Verify_Content'}"}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/resversion.png" alt="'.$lt{cv}.'" onclick=\'javascript:injectData(document.courseverify, "dummy", "versions", "'.$lt{'cv'}.'")\' />' - =>"<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"versions\", \"$lt{'cv'}\")'>$lt{'cv'}</a>$help{'Check_Resource_Versions'}"}, - ); - if($dumpbut ne ''){ - push @list, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/dump.png" alt="'.$lt{dcd}.'" />'=>$dumpbut}; - } - push @list, ({'<img class="LC_noBorder LC_middle" src="/res/adm/pages/imsexport.png" alt="'.$lt{imse}.'" onclick="javascript:injectData(document.courseverify, \'dummy\', \'exportcourse\', \''.&mt('IMS Export').'\');" />' - =>$exportbut}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/symbs.png" alt="'.$lt{ls}.'" onclick=\'javascript:injectData(document.courseverify, "dummy", "listsymbs", "'.$lt{'ls'}.'")\' />' - =>"<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"listsymbs\", \"$lt{'ls'}\")'>$lt{'ls'}</a><input type='hidden' name='folder' value='$env{'form.folder'}' />"}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/document-properties.png" alt="'.$lt{sl}.'" onclick=\'javascript:injectData(document.courseverify, "dummy", "docslog", "'.$lt{'sl'}.'")\' />' - =>"<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"docslog\", \"$lt{'sl'}\")'>$lt{'sl'}</a>"}, - ); - return '<form action="/adm/coursedocs" method="post" name="courseverify"><input type="hidden" id="dummy" />'.create_form_ul(create_list_elements(@list)).'</form>'; - +sub decompression_info { + my ($destination,$dir_root) = &embedded_destination(); + my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'}; + my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'}; + my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'}; + my $container='sequence'; + my ($pathitem,$hiddenelem); + my @hiddens = ('newidx','comment','position','folderpath','archiveurl'); + if ($env{'form.folderpath'} =~ /\:1$/) { + $container='page'; + } + unshift(@hiddens,$pathitem); + foreach my $item (@hiddens) { + if ($env{'form.'.$item}) { + $hiddenelem .= '<input type="hidden" name="'.$item.'" value="'. + &HTML::Entities::encode($env{'form.'.$item},'<>&"').'" />'."\n"; + } + } + return ($destination,$dir_root,$londocroot,$docudom,$docuname,$container, + $hiddenelem); +} + +sub decompression_phase_one { + my ($dir,$file,$warning,$error,$output); + my ($destination,$dir_root,$londocroot,$docudom,$docuname,$container,$hiddenelem)= + &decompression_info(); + if ($env{'form.archiveurl'} !~ m{^/uploaded/\Q$docudom/$docuname/\E(?:docs|supplemental)/(?:default|\d+).*/([^/]+)$}) { + $error = &mt('Archive file "[_1]" not in the expected location.',$env{'form.archiveurl'}); + } else { + my $file = $1; + $output = + &Apache::loncommon::process_decompression($docudom,$docuname,$file, + $destination,$dir_root, + $hiddenelem); + if ($env{'form.autoextract_camtasia'}) { + $output .= &remove_archive($docudom,$docuname,$container); + } + } + if ($error) { + $output .= '<p class="LC_error">'.&mt('Not extracted.').'<br />'. + $error.'</p>'."\n"; + } + if ($warning) { + $output .= '<p class="LC_warning">'.$warning.'</p>'."\n"; + } + return $output; +} + +sub decompression_phase_two { + my ($destination,$dir_root,$londocroot,$docudom,$docuname,$container,$hiddenelem)= + &decompression_info(); + my $output; + if ($env{'form.archivedelete'}) { + $output = &remove_archive($docudom,$docuname,$container); + } + $output .= + &Apache::loncommon::process_extracted_files('coursedocs',$docudom,$docuname, + $destination,$dir_root,$hiddenelem); + return $output; +} + +sub remove_archive { + my ($docudom,$docuname,$container) = @_; + my $map = $env{'form.folder'}.'.'.$container; + my ($output,$delwarning,$delresult,$url); + my ($errtext,$fatal) = &mapread($docuname,$docudom,$map); + if ($fatal) { + if ($container eq 'page') { + $delwarning = &mt('An error occurred retrieving the contents of the current page.'); + } else { + $delwarning = &mt('An error occurred retrieving the contents of the current folder.'); + } + $delwarning .= ' '.&mt('As a result the archive file has not been removed.'); + } else { + my $currcmd = $env{'form.cmd'}; + my $position = $env{'form.position'}; + my $archiveidx = $position; + if ($position > 0) { + if (($env{'form.autoextract_camtasia'}) && (scalar(@LONCAPA::map::order) == 2)) { + $archiveidx = $position-1; + } + $env{'form.cmd'} = 'remove_'.$archiveidx; + my ($title,$url,@rrest) = + split(/:/,$LONCAPA::map::resources[$LONCAPA::map::order[$archiveidx]]); + if ($url eq $env{'form.archiveurl'}) { + if (&handle_edit_cmd($docuname,$docudom)) { + ($errtext,$fatal) = &storemap($docuname,$docudom,$map,1); + if ($fatal) { + if ($container eq 'page') { + $delwarning = &mt('An error occurred updating the contents of the current page.'); + } else { + $delwarning = &mt('An error occurred updating the contents of the current folder.'); + } + } else { + $delresult = &mt('Archive file removed.'); + } + } + } else { + $delwarning .= &mt('Archive file had unexpected item number in folder.'). + ' '.&mt('As a result the archive file has not been removed.'); + } + } + $env{'form.cmd'} = $currcmd; + } + if ($delwarning) { + $output = '<p class="LC_warning">'. + $delwarning. + '</p>'; + } + if ($delresult) { + $output .= '<p class="LC_info">'. + $delresult. + '</p>'; + } + return $output; } +sub generate_admin_menu { + my ($crstype) = @_; + my $lc_crstype = lc($crstype); + my ($home,$other,%outhash)=&authorhosts(); + my %lt= ( # do not translate here + 'vc' => 'Verify Content', + 'cv' => 'Check/Set Resource Versions', + 'ls' => 'List Resource Identifiers', + 'imse' => 'Export contents to IMS Archive', + 'dcd' => "Copy $crstype Content to Authoring Space", + ); + my ($candump,$dumpurl); + if ($home + $other > 0) { + $candump = 'F'; + if ($home) { + $dumpurl = "javascript:injectData(document.courseverify,'dummy','dumpcourse','$lt{'dcd'}')"; + } else { + my @hosts; + foreach my $aurole (keys(%outhash)) { + unless(grep(/^\Q$outhash{$aurole}\E/,@hosts)) { + push(@hosts,$outhash{$aurole}); + } + } + if (@hosts == 1) { + my $switchto = '/adm/switchserver?otherserver='.$hosts[0]. + '&role='. + &HTML::Entities::encode($env{'request.role'},'"<>&').'&origurl='. + &HTML::Entities::encode('/adm/coursedocs?dumpcourse=1','"<>&'); + $dumpurl = "javascript:dump_needs_switchserver('$switchto')"; + } else { + $dumpurl = "javascript:choose_switchserver_window()"; + } + } + } + my @menu= + ({ categorytitle=>'Administration', + items =>[ + { linktext => $lt{'vc'}, + url => "javascript:injectData(document.courseverify,'dummy','verify','$lt{'vc'}')", + permission => 'F', + help => 'Docs_Verify_Content', + icon => 'verify.png', + linktitle => 'Verify contents can be retrieved/rendered', + }, + { linktext => $lt{'cv'}, + url => "javascript:injectData(document.courseverify,'dummy','versions','$lt{'cv'}')", + permission => 'F', + help => 'Docs_Check_Resource_Versions', + icon => 'resversion.png', + linktitle => "View version information for resources in your $lc_crstype, and fix/unfix use of specific versions", + }, + { linktext => $lt{'ls'}, + url => "javascript:injectData(document.courseverify,'dummy','listsymbs','$lt{'ls'}')", + permission => 'F', + #help => '', + icon => 'symbs.png', + linktitle => "List the unique identifier used for each resource instance in your $lc_crstype" + }, + ] + }, + { categorytitle=>'Export', + items =>[ + { linktext => $lt{'imse'}, + url => "javascript:injectData(document.courseverify,'dummy','exportcourse','$lt{'imse'}')", + permission => 'F', + help => 'Docs_Export_Course_Docs', + icon => 'imsexport.png', + linktitle => $lt{'imse'}, + }, + { linktext => $lt{'dcd'}, + url => $dumpurl, + permission => $candump, + help => 'Docs_Dump_Course_Docs', + icon => 'dump.png', + linktitle => $lt{'dcd'}, + }, + ] + }); + return '<form action="/adm/coursedocs" method="post" name="courseverify">'."\n". + '<input type="hidden" id="dummy" />'."\n". + &Apache::lonhtmlcommon::generate_menu(@menu)."\n". + '</form>'; +} sub generate_edit_table { - my ($tid,$orderhash_ref) = @_; + my ($tid,$orderhash_ref,$to_show,$iconpath,$jumpto,$readfile, + $need_save,$copyfolder) = @_; return unless(ref($orderhash_ref) eq 'HASH'); my %orderhash = %{$orderhash_ref}; my $form; my $activetab; my $active; - if($env{'form.active'} ne ''){ + if (($env{'form.active'} ne '') && ($env{'form.active'} ne '00')) { $activetab = $env{'form.active'}; } - $form = '<div class="LC_Box" style="margin-right:0">'; - $form .= '<ul id="navigation'.$tid.'" class="LC_TabContent">'; - foreach my $name (sort(keys(%orderhash))){ + my $backicon = $iconpath.'clickhere.gif'; + my $backtext = &mt('Exit Editor'); + $form = '<div class="LC_Box" style="margin:0;">'. + '<ul id="navigation'.$tid.'" class="LC_TabContent">'."\n". + '<li class="goback">'. + '<a href="javascript:toContents('."'$jumpto'".');">'. + '<img src="'.$backicon.'" class="LC_icon" style="border: none; vertical-align: top;"'. + ' alt="'.$backtext.'" />'.$backtext.'</a></li>'."\n". + '<li>'. + '<a href="javascript:groupopen('."'$readfile'".',1);">'. + &mt('Undo Delete').'</a></li>'."\n"; + if ($env{'form.docslog'}) { + $form .= '<li class="active">'; + } else { + $form .= '<li>'; + } + $form .= '<a href="javascript:toggleHistoryDisp(1);">'. + &mt('History').'</a></li>'."\n"; + if ($env{'form.docslog'}) { + $form .= '<li><a href="javascript:toggleHistoryDisp(0);">'. + &mt('Edit').'</a></li>'."\n"; + } + foreach my $name (reverse(sort(keys(%orderhash)))) { if($name ne '00'){ if($activetab eq '' || $activetab ne $name){ $active = ''; }elsif($activetab eq $name){ $active = 'class="active"'; } - $form .= '<li '.$active - .' onmouseover="javascript:showPage(this, \''.$name.$tid.'\', \'navigation'.$tid.'\',\'content'.$tid.'\');"' - .' onclick="javascript:showPage(this, \''.$name.$tid.'\', \'navigation'.$tid.'\',\'content'.$tid.'\');"><a href="javascript:;"><b>'.&mt(${$orderhash{$name}}[0]).'</b></a></li>'; + $form .= '<li style="float:right" '.$active + .' onclick="javascript:showPage(this, \''.$name.$tid.'\', \'navigation'.$tid.'\',\'content'.$tid.'\');"><a href="javascript:;"><b>'.&mt(${$orderhash{$name}}[0]).'</b></a></li>'."\n"; } else { - $form .= '<li '.$active.'>'.${$orderhash{$name}}[1].'</li>'; + $form .= '<li style="float:right">'.${$orderhash{$name}}[1].'</li>'."\n"; } } - $form .= '</ul>'; - $form .= '<div id="content'.$tid.'" style="padding: 0 0; margin: 0 0; clear: both;">'; + $form .= '</ul>'."\n"; + $form .= '<div id="content'.$tid.'" style="padding: 0 0; margin: 0 0; overflow: hidden; clear:right">'."\n"; + + if ($to_show ne '') { + my $saveform; + if ($need_save) { + my $button = &mt('Make changes'); + my $path; + if ($env{'form.folderpath'}) { + $path = + &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); + } + $saveform = <<"END"; +<div id="multisave" style="display:none; clear:both;" > +<form name="saveactions" method="post" action="/adm/coursedocs" onsubmit="return checkSubmits();"> +<input type="hidden" name="folderpath" value="$path" /> +<input type="hidden" name="symb" value="$env{'form.symb'}" /> +<input type="hidden" name="allhiddenresource" value="" /> +<input type="hidden" name="allencrypturl" value="" /> +<input type="hidden" name="allrandompick" value="" /> +<input type="hidden" name="allrandomorder" value="" /> +<input type="hidden" name="changeparms" value="" /> +<input type="hidden" name="multiremove" value="" /> +<input type="hidden" name="multicut" value="" /> +<input type="hidden" name="multicopy" value="" /> +<input type="hidden" name="multichange" value="" /> +<input type="hidden" name="copyfolder" value="$copyfolder" /> +<input type="submit" name="savemultiples" value="$button" /> +</form> +</div> +END + } + $form .= '<div style="padding:0;margin:0;float:left">'.$to_show.'</div>'.$saveform."\n"; + } foreach my $field (keys(%orderhash)){ if($field ne '00'){ if($activetab eq '' || $activetab ne $field){ - $active = 'style="display: none;"'; + $active = 'style="display: none;float:left"'; }elsif($activetab eq $field){ - $active = 'style="display:block;"'; + $active = 'style="display:block;float:left"'; } $form .= '<div id="'.$field.$tid.'"' .' class="LC_ContentBox" '.$active.'>'.${$orderhash{$field}}[1] - .'</div>'; + .'</div>'."\n"; } } - $form .= '</div></div>'; - + unless ($env{'form.docslog'}) { + $form .= '</div></div>'."\n"; + } return $form; } sub editing_js { - my ($udom,$uname) = @_; - my $now = time(); + my ($udom,$uname,$supplementalflag) = @_; my %lt = &Apache::lonlocal::texthash( p_mnf => 'Name of New Folder', t_mnf => 'New Folder', p_mnp => 'Name of New Page', t_mnp => 'New Page', - p_mxu => 'Title for the Uploaded Score', + p_mxu => 'Title for the External Score', p_msp => 'Name of Simple Course Page', p_msb => 'Title for the Problem', p_mdb => 'Title for the Drop Box', p_mbb => 'Title for the Discussion Board', + p_mwp => 'Title for Web Page', p_mab => "Enter user:domain for User's Personal Information Page", p_mab2 => 'Personal Information Page of ', p_mab_alrt1 => 'Not a valid user:domain', @@ -3572,23 +5774,66 @@ sub editing_js { p_rmr1 => 'WARNING: Removing a resource makes associated grades and scores inaccessible!', p_rmr2a => 'Remove[_99]', p_rmr2b => '?[_99]', + p_rmr3a => 'Remove those [_2]', + p_rmr3b => 'items?[_2]', p_ctr1a => 'WARNING: Cutting a resource makes associated grades and scores inaccessible!', p_ctr1b => 'Grades remain inaccessible if resource is pasted into another folder.', p_ctr2a => 'Cut[_98]', - p_ctr2b => '?[_98]' + p_ctr2b => '?[_98]', + p_ctr3a => 'Cut those[_2]', + p_ctr3b => 'items?[_2]', + rpck => 'Enter number to pick (e.g., 3)', + imsfile => 'You must choose an IMS package for import', + imscms => 'You must select which Course Management System was the source of the IMS package', + invurl => 'Invalid URL', + titbl => 'Title is blank', + more => '(More ...)', + less => '(Less ...)', + noor => 'No actions selected or changes to settings specified.', + noch => 'No changes to settings specified.', + noac => 'No actions selected.', ); my $crstype = &Apache::loncommon::course_type(); my $docs_folderpath = &HTML::Entities::encode($env{'environment.internal.'.$env{'request.course.id'}.'.docs_folderpath.folderpath'},'<>&"'); - my $docs_pagepath = &HTML::Entities::encode($env{'environment.internal.'.$env{'request.course.id'}.'.docs_folderpath.pagepath'},'<>&"'); my $main_container_page; - if ($docs_folderpath eq '') { - if ($docs_pagepath ne '') { - $main_container_page = 1; + if (&HTML::Entities::decode($env{'environment.internal.'.$env{'request.course.id'}.'.docs_folderpath.folderpath'}) =~ /\:1$/) { + $main_container_page = 1; + } + my $toplevelmain = + &escape(&mt('Main Content').':::::'); + my $toplevelsupp = &supplemental_base(); + + my $backtourl; + if ($env{'docs.exit.'.$env{'request.course.id'}} =~ /^direct_(.+)$/) { + my $caller = $1; + if ($caller =~ /^supplemental/) { + $backtourl = '/adm/supplemental?folderpath='.&escape($caller); + } else { + my ($map,$id,$res)=&Apache::lonnet::decode_symb($caller); + $res = &Apache::lonnet::clutter($res); + if (&Apache::lonnet::is_on_map($res)) { + $backtourl = &HTML::Entities::encode(&Apache::lonnet::clutter($res),'<>&"').'?symb='. + &HTML::Entities::encode($caller,'<>&"'); + } else { + $backtourl = '/adm/navmaps'; + } } + } elsif ($env{'docs.exit.'.$env{'request.course.id'}} eq '/adm/menu') { + $backtourl = '/adm/menu'; + } elsif ($supplementalflag) { + $backtourl = '/adm/supplemental'; + } else { + $backtourl = '/adm/navmaps'; + } + + my $fieldsets = "'ext','doc'"; + unless ($main_container_page) { + $fieldsets .=",'ims'"; + } + if ($supplementalflag) { + $fieldsets = "'suppext','suppdoc'"; } - my $toplevelmain = 'default&Main%20'.$crstype.'%20Documents'; - my $toplevelsupp = 'supplemental&Supplemental%20'.$crstype.'%20Documents'; return <<ENDNEWSCRIPT; function makenewfolder(targetform,folderseq) { @@ -3607,22 +5852,6 @@ function makenewpage(targetform,folderse } } -function makenewext(targetname) { - this.document.forms.extimport.useform.value=targetname; - this.document.forms.extimport.title.value=''; - this.document.forms.extimport.url.value=''; - this.document.forms.extimport.residx.value=''; - window.open('/adm/rat/extpickframe.html'); -} - -function edittext(targetname,residx,title,url) { - this.document.forms.extimport.useform.value=targetname; - this.document.forms.extimport.residx.value=residx; - this.document.forms.extimport.url.value=url; - this.document.forms.extimport.title.value=title; - window.open('/adm/rat/extpickframe.html'); -} - function makeexamupload() { var title=prompt('$lt{"p_mxu"}'); if (title) { @@ -3636,11 +5865,26 @@ function makesmppage() { var title=prompt('$lt{"p_msp"}'); if (title) { this.document.forms.newsmppg.importdetail.value= - escape(title)+'=/adm/$udom/$uname/$now/smppg'; + escape(title)+'=/adm/$udom/$uname/new/smppg'; this.document.forms.newsmppg.submit(); } } +function makewebpage(type) { + var title=prompt('$lt{"p_mwp"}'); + var formname; + if (type == 'supp') { + formname = this.document.forms.supwebpage; + } else { + formname = this.document.forms.newwebpage; + } + if (title) { + var webpage = formname.importdetail.value; + formname.importdetail.value = escape(title)+'='+webpage; + formname.submit(); + } +} + function makesmpproblem() { var title=prompt('$lt{"p_msb"}'); if (title) { @@ -3663,7 +5907,7 @@ function makebulboard() { var title=prompt('$lt{"p_mbb"}'); if (title) { this.document.forms.newbul.importdetail.value= - escape(title)+'=/adm/$udom/$uname/$now/bulletinboard'; + escape(title)+'=/adm/$udom/$uname/new/bulletinboard'; this.document.forms.newbul.submit(); } } @@ -3687,101 +5931,341 @@ function makeabout() { } } -function makeims() { -var caller = document.forms.ims.folder.value; -var newlocation = "/adm/imsimportdocs?folder="+caller+"&phase=one"; -newWindow = window.open("","IMSimport","HEIGHT=700,WIDTH=750,scrollbars=yes"); -newWindow.location.href = newlocation; +function toggleUpload(caller) { + var blocks = Array($fieldsets); + for (var i=0; i<blocks.length; i++) { + var disp = 'none'; + if (caller == blocks[i]) { + var curr = document.getElementById('upload'+caller+'form').style.display; + if (curr == 'none') { + disp='block'; + } + } + document.getElementById('upload'+blocks[i]+'form').style.display=disp; + } + resize_scrollbox('contentscroll','1','1'); + return; } +function toggleMap(caller) { + var disp = 'none'; + if (document.getElementById('importmapform')) { + if (caller == 'map') { + var curr = document.getElementById('importmapform').style.display; + if (curr == 'none') { + disp='block'; + } + } + document.getElementById('importmapform').style.display=disp; + resize_scrollbox('contentscroll','1','1'); + } + return; +} -function finishpick() { -var title=this.document.forms.extimport.title.value; -var url=this.document.forms.extimport.url.value; -var form=this.document.forms.extimport.useform.value; -var residx=this.document.forms.extimport.residx.value; -eval('this.document.forms.'+form+'.importdetail.value="'+title+'='+url+'='+residx+'";this.document.forms.'+form+'.submit();'); +function makeims(imsform) { + if ((imsform.uploaddoc.value == '') || (!imsform.uploaddoc.value)) { + alert("$lt{'imsfile'}"); + return; + } + if (imsform.source.selectedIndex == 0) { + alert("$lt{'imscms'}"); + return; + } + newWindow = window.open('', 'IMSimport',"HEIGHT=700,WIDTH=750,scrollbars=yes"); + imsform.submit(); } -function changename(folderpath,index,oldtitle,container,pagesymb) { +function changename(folderpath,index,oldtitle) { var title=prompt('$lt{"p_chn"}',oldtitle); if (title) { -this.document.forms.renameform.markcopy.value=-1; +this.document.forms.renameform.markcopy.value=''; this.document.forms.renameform.title.value=title; this.document.forms.renameform.cmd.value='rename_'+index; -if (container == 'sequence') { - this.document.forms.renameform.folderpath.value=folderpath; -} -if (container == 'page') { - this.document.forms.renameform.pagepath.value=folderpath; - this.document.forms.renameform.pagesymb.value=pagesymb; -} +this.document.forms.renameform.folderpath.value=folderpath; this.document.forms.renameform.submit(); } } -function removeres(folderpath,index,oldtitle,container,pagesymb,skip_confirm) { -if (skip_confirm || confirm('$lt{"p_rmr1"}\\n\\n$lt{"p_rmr2a"} "'+oldtitle+'" $lt{"p_rmr2b"}')) { -this.document.forms.renameform.markcopy.value=-1; -this.document.forms.renameform.cmd.value='del_'+index; -if (container == 'sequence') { - this.document.forms.renameform.folderpath.value=folderpath; -} -if (container == 'page') { - this.document.forms.renameform.pagepath.value=folderpath; - this.document.forms.renameform.pagesymb.value=pagesymb; -} -this.document.forms.renameform.submit(); -} +function updatePick(targetform,index,caller) { + var pickitem; + var picknumitem; + var picknumtext; + if (index == 'all') { + pickitem = document.getElementById('randompickall'); + picknumitem = document.getElementById('rpicknumall'); + picknumtext = document.getElementById('rpicktextall'); + } else { + pickitem = document.getElementById('randompick_'+index); + picknumitem = document.getElementById('rpicknum_'+index); + picknumtext = document.getElementById('randompicknum_'+index); + } + if (pickitem.checked) { + var picknum=prompt('$lt{"rpck"}',picknumitem.value); + if (picknum == '' || picknum == null) { + if (caller == 'check') { + pickitem.checked=false; + if (index == 'all') { + picknumtext.innerHTML = ''; + if (caller == 'link') { + propagateState(targetform,'rpicknum'); + } + } else { + checkForSubmit(targetform,'randompick','settings'); + } + } + } else { + picknum.toString(); + var regexdigit=/^\\d+\$/; + if (regexdigit.test(picknum)) { + picknumitem.value = picknum; + if (index == 'all') { + picknumtext.innerHTML = ' <a href="javascript:updatePick(document.cumulativesettings,\\'all\\',\\'link\\');">'+picknum+'</a>'; + if (caller == 'link') { + propagateState(targetform,'rpicknum'); + } + } else { + picknumtext.innerHTML = ' <a href="javascript:updatePick(document.edit_randompick_'+index+',\\''+index+'\\',\\'link\\');">'+picknum+'</a>'; + checkForSubmit(targetform,'randompick','settings'); + } + } else { + if (caller == 'check') { + if (index == 'all') { + picknumtext.innerHTML = ''; + if (caller == 'link') { + propagateState(targetform,'rpicknum'); + } + } else { + pickitem.checked=false; + checkForSubmit(targetform,'randompick','settings'); + } + } + return; + } + } + } else { + picknumitem.value = ''; + picknumtext.innerHTML = ''; + if (index == 'all') { + if (caller == 'link') { + propagateState(targetform,'rpicknum'); + } + } else { + checkForSubmit(targetform,'randompick','settings'); + } + } } -function cutres(folderpath,index,oldtitle,container,pagesymb,folder,skip_confirm) { -if (skip_confirm || confirm('$lt{"p_ctr1a"}\\n$lt{"p_ctr1b"}\\n\\n$lt{"p_ctr2a"} "'+oldtitle+'" $lt{"p_ctr2b"}')) { -this.document.forms.renameform.cmd.value='cut_'+index; -this.document.forms.renameform.markcopy.value=index; -this.document.forms.renameform.copyfolder.value=folder+'.'+container; -if (container == 'sequence') { - this.document.forms.renameform.folderpath.value=folderpath; -} -if (container == 'page') { - this.document.forms.renameform.pagepath.value=folderpath; - this.document.forms.renameform.pagesymb.value=pagesymb; -} -this.document.forms.renameform.submit(); -} +function propagateState(form,param) { + if (document.getElementById(param+'all')) { + var setcheck = 0; + var rpick = 0; + if (param == 'rpicknum') { + if (document.getElementById('randompickall')) { + if (document.getElementById('randompickall').checked) { + if (document.getElementById('rpicknumall')) { + rpick = document.getElementById('rpicknumall').value; + } + } + } + } else { + if (document.getElementById(param+'all').checked) { + setcheck = 1; + } + } + var allidxlist; + if ((param == 'remove') || (param == 'cut') || (param == 'copy')) { + if (document.getElementById('all'+param+'idx')) { + allidxlist = document.getElementById('all'+param+'idx').value; + } + var actions = new Array ('remove','cut','copy'); + for (var i=0; i<actions.length; i++) { + if (actions[i] != param) { + if (document.getElementById(actions[i]+'all')) { + document.getElementById(actions[i]+'all').checked = false; + } + } + } + } + if ((param == 'encrypturl') || (param == 'hiddenresource')) { + allidxlist = form.allidx.value; + } + if ((param == 'randompick') || (param == 'rpicknum') || (param == 'randomorder')) { + allidxlist = form.allmapidx.value; + } + if ((allidxlist != '') && (allidxlist != null)) { + var allidxs = allidxlist.split(','); + if (allidxs.length > 1) { + for (var i=0; i<allidxs.length; i++) { + if (document.getElementById(param+'_'+allidxs[i])) { + if (param == 'rpicknum') { + if (document.getElementById('randompick_'+allidxs[i])) { + if (document.getElementById('randompick_'+allidxs[i]).checked) { + document.getElementById(param+'_'+allidxs[i]).value = rpick; + if (rpick > 0) { + document.getElementById('randompicknum_'+allidxs[i]).innerHTML = ': <a href="javascript:updatePick(document.edit_randompick_'+allidxs[i]+',\\''+allidxs[i]+'\\',\\'link\\')">'+rpick+'</a>'; + } else { + document.getElementById('randompicknum_'+allidxs[i]).innerHTML = ''; + } + } + } + } else { + if (setcheck == 1) { + document.getElementById(param+'_'+allidxs[i]).checked = true; + } else { + document.getElementById(param+'_'+allidxs[i]).checked = false; + if (param == 'randompick') { + document.getElementById('randompicknum_'+allidxs[i]).innerHTML = ''; + } + } + } + } + } + if (setcheck == 1) { + if ((param == 'remove') || (param == 'cut') || (param == 'copy')) { + var actions = new Array('copy','cut','remove'); + for (var i=0; i<actions.length; i++) { + var otheractions; + var otheridxs; + if (actions[i] === param) { + continue; + } else { + if (document.getElementById('all'+actions[i]+'idx')) { + otheractions = document.getElementById('all'+actions[i]+'idx').value; + otheridxs = otheractions.split(','); + if (otheridxs.length > 1) { + for (var j=0; j<otheridxs.length; j++) { + if (document.getElementById(actions[i]+'_'+otheridxs[j])) { + document.getElementById(actions[i]+'_'+otheridxs[j]).checked = false; + } + } + } + } + } + } + } + } + } + } + } + return; } -function markcopy(folderpath,index,oldtitle,container,pagesymb,folder) { -this.document.forms.renameform.markcopy.value=index; -this.document.forms.renameform.copyfolder.value=folder+'.'+container; -if (container == 'sequence') { -this.document.forms.renameform.folderpath.value=folderpath; -} -if (container == 'page') { -this.document.forms.renameform.pagepath.value=folderpath; -this.document.forms.renameform.pagesymb.value=pagesymb; +function checkForSubmit(targetform,param,context,idx,folderpath,index,oldtitle,skip_confirm,container,folder) { + var dosettings; + var doaction; + var control = document.togglemultsettings; + if (context == 'actions') { + control = document.togglemultactions; + doaction = 1; + } else { + dosettings = 1; + } + if (control) { + if (control.showmultpick.length) { + for (var i=0; i<control.showmultpick.length; i++) { + if (control.showmultpick[i].checked) { + if (control.showmultpick[i].value == 1) { + if (context == 'settings') { + dosettings = 0; + } else { + doaction = 0; + } + } + } + } + } + } + if (context == 'settings') { + if (dosettings == 1) { + targetform.changeparms.value=param; + targetform.submit(); + } + } + if (context == 'actions') { + if (doaction == 1) { + targetform.cmd.value=param+'_'+index; + targetform.folderpath.value=folderpath; + targetform.markcopy.value=idx+':'+param; + targetform.copyfolder.value=folder+'.'+container; + if (param == 'remove') { + if (skip_confirm || confirm('$lt{"p_rmr1"}\\n\\n$lt{"p_rmr2a"} "'+oldtitle+'" $lt{"p_rmr2b"}')) { + targetform.markcopy.value=''; + targetform.copyfolder.value=''; + targetform.submit(); + } + } + if (param == 'cut') { + if (skip_confirm || confirm('$lt{"p_ctr1a"}\\n$lt{"p_ctr1b"}\\n\\n$lt{"p_ctr2a"} "'+oldtitle+'" $lt{"p_ctr2b"}')) { + targetform.submit(); + return; + } + } + if (param == 'copy') { + targetform.submit(); + return; + } + targetform.markcopy.value=''; + targetform.copyfolder.value=''; + targetform.cmd.value=''; + targetform.folderpath.value=''; + return; + } else { + if (document.getElementById(param+'_'+idx)) { + item = document.getElementById(param+'_'+idx); + if (item.type == 'checkbox') { + if (item.checked) { + item.checked = false; + } else { + item.checked = true; + singleCheck(item,idx,param); + } + } + } + } + } + return; } -this.document.forms.renameform.submit(); + +function singleCheck(caller,idx,action) { + actions = new Array('cut','copy','remove'); + if (caller.checked) { + for (var i=0; i<actions.length; i++) { + if (actions[i] != action) { + if (document.getElementById(actions[i]+'_'+idx)) { + if (document.getElementById(actions[i]+'_'+idx).checked) { + document.getElementById(actions[i]+'_'+idx).checked = false; + } + } + } + } + } + return; } function unselectInactive(nav) { currentNav = document.getElementById(nav); currentLis = currentNav.getElementsByTagName('LI'); for (i = 0; i < currentLis.length; i++) { - if(currentLis[i].className == 'right active' || currentLis[i].className == 'right'){ + if (currentLis[i].className == 'goback') { + currentLis[i].className = 'goback'; + } else { + if (currentLis[i].className == 'right active' || currentLis[i].className == 'right') { currentLis[i].className = 'right'; - }else{ + } else { currentLis[i].className = 'i'; - } + } + } } } function hideAll(current, nav, data) { unselectInactive(nav); -if(current.className == 'right'){ - current.className = 'right active' - }else{ - current.className = 'active'; +if (current) { + if (current.className == 'right'){ + current.className = 'right active' + } else { + current.className = 'active'; + } } currentData = document.getElementById(data); currentDivs = currentData.getElementsByTagName('DIV'); @@ -3812,17 +6296,31 @@ function openTabs(pageId) { } function showPage(current, pageId, nav, data) { + currstate = current.className; hideAll(current, nav, data); openTabs(pageId); unselectInactive(nav); - current.className = 'active'; + if ((currstate == 'active') || (currstate == 'right active')) { + if (currstate == 'active') { + current.className = ''; + } else { + current.className = 'right'; + } + activeTab = ''; + toggleUpload(); + toggleMap(); + resize_scrollbox('contentscroll','1','0'); + return; + } else { + current.className = 'active'; + } currentData = document.getElementById(pageId); currentData.style.display = 'block'; + activeTab = pageId; + toggleUpload(); + toggleMap(); if (nav == 'mainnav') { var storedpath = "$docs_folderpath"; - if (storedpath == '') { - storedpath = "$docs_pagepath"; - } var storedpage = "$main_container_page"; var reg = new RegExp("^supplemental"); if (pageId == 'mainCourseDocuments') { @@ -3852,18 +6350,451 @@ function showPage(current, pageId, nav, } } } + resize_scrollbox('contentscroll','1','0'); return false; } -function injectData(current, hiddenField, name, value) { - currentElement = document.getElementById(hiddenField); - currentElement.name = name; - currentElement.value = value; - current.submit(); +function toContents(jumpto) { + var newurl = '$backtourl'; + if ((newurl == '/adm/navmaps') && (jumpto != '')) { + newurl = newurl+'?postdata='+jumpto; + } + location.href=newurl; +} + +function togglePick(caller,value) { + var disp = 'none'; + if (document.getElementById('multi'+caller)) { + var curr = document.getElementById('multi'+caller).style.display; + if (value == 1) { + disp='block'; + } + if (curr == disp) { + return; + } + document.getElementById('multi'+caller).style.display=disp; + if (value == 1) { + document.getElementById('more'+caller).innerHTML = ' <a href="javascript:toggleCheckUncheck(\\''+caller+'\\',1);" style="text-decoration:none;">$lt{'more'}</a>'; + } else { + document.getElementById('more'+caller).innerHTML = ''; + } + if (caller == 'actions') { + setClass(value); + setBoxes(value); + } + } + var showButton = multiSettings(); + if (showButton != 1) { + showButton = multiActions(); + } + if (document.getElementById('multisave')) { + if (showButton == 1) { + document.getElementById('multisave').style.display='block'; + } else { + document.getElementById('multisave').style.display='none'; + } + } + resize_scrollbox('contentscroll','1','1'); + return; +} + +function toggleCheckUncheck(caller,more) { + if (more == 1) { + document.getElementById('more'+caller).innerHTML = ' <a href="javascript:toggleCheckUncheck(\\''+caller+'\\',0);" style="text-decoration:none;">$lt{'less'}</a>'; + document.getElementById('allfields'+caller).style.display='block'; + } else { + document.getElementById('more'+caller).innerHTML = ' <a href="javascript:toggleCheckUncheck(\\''+caller+'\\',1);" style="text-decoration:none;">$lt{'more'}</a>'; + document.getElementById('allfields'+caller).style.display='none'; + } + resize_scrollbox('contentscroll','1','1'); +} + +function multiSettings() { + var inuse = 0; + var settingsform = document.togglemultsettings; + if (settingsform.showmultpick.length > 1) { + for (var i=0; i<settingsform.showmultpick.length; i++) { + if (settingsform.showmultpick[i].checked) { + if (settingsform.showmultpick[i].value == 1) { + inuse = 1; + } + } + } + } + return inuse; +} + +function multiActions() { + var inuse = 0; + var actionsform = document.togglemultactions; + if (actionsform.showmultpick.length > 1) { + for (var i=0; i<actionsform.showmultpick.length; i++) { + if (actionsform.showmultpick[i].checked) { + if (actionsform.showmultpick[i].value == 1) { + inuse = 1; + } + } + } + } + return inuse; +} + +function checkSubmits() { + var numchanges = 0; + var form = document.saveactions; + var doactions = multiActions(); + var cutwarnings = 0; + var remwarnings = 0; + if (doactions == 1) { + var remidxlist = document.cumulativeactions.allremoveidx.value; + if ((remidxlist != '') && (remidxlist != null)) { + var remidxs = remidxlist.split(','); + for (var i=0; i<remidxs.length; i++) { + if (document.getElementById('remove_'+remidxs[i])) { + if (document.getElementById('remove_'+remidxs[i]).checked) { + form.multiremove.value += remidxs[i]+','; + numchanges ++; + if (document.getElementById('skip_remove_'+remidxs[i])) { + if (document.getElementById('skip_remove_'+remidxs[i]).value == 0) { + remwarnings ++; + } + } + } + } + } + } + var cutidxlist = document.cumulativeactions.allcutidx.value; + if ((cutidxlist != '') && (cutidxlist != null)) { + var cutidxs = cutidxlist.split(','); + for (var i=0; i<cutidxs.length; i++) { + if (document.getElementById('cut_'+cutidxs[i])) { + if (document.getElementById('cut_'+cutidxs[i]).checked == true) { + form.multicut.value += cutidxs[i]+','; + numchanges ++; + if (document.getElementById('skip_cut_'+cutidxs[i])) { + if (document.getElementById('skip_cut_'+cutidxs[i]).value == 0) { + cutwarnings ++; + } + } + } + } + } + } + var copyidxlist = document.cumulativeactions.allcopyidx.value; + if ((copyidxlist != '') && (copyidxlist != null)) { + var copyidxs = copyidxlist.split(','); + for (var i=0; i<copyidxs.length; i++) { + if (document.getElementById('copy_'+copyidxs[i])) { + if (document.getElementById('copy_'+copyidxs[i]).checked) { + form.multicopy.value += copyidxs[i]+','; + numchanges ++; + } + } + } + } + if (numchanges > 0) { + form.multichange.value = numchanges; + } + } + var dosettings = multiSettings(); + var haschanges = 0; + if (dosettings == 1) { + form.allencrypturl.value = ''; + form.allhiddenresource.value = ''; + form.changeparms.value = 'all'; + var patt=new RegExp(",\$"); + var allidxlist = document.cumulativesettings.allidx.value; + if ((allidxlist != '') && (allidxlist != null)) { + var allidxs = allidxlist.split(','); + if (allidxs.length > 1) { + for (var i=0; i<allidxs.length; i++) { + if (document.getElementById('hiddenresource_'+allidxs[i])) { + if (document.getElementById('hiddenresource_'+allidxs[i]).checked) { + form.allhiddenresource.value += allidxs[i]+','; + } + } + if (document.getElementById('encrypturl_'+allidxs[i])) { + if (document.getElementById('encrypturl_'+allidxs[i]).checked) { + form.allencrypturl.value += allidxs[i]+','; + } + } + } + form.allhiddenresource.value = form.allhiddenresource.value.replace(patt,""); + form.allencrypturl.value = form.allencrypturl.value.replace(patt,""); + } + } + form.allrandompick.value = ''; + form.allrandomorder.value = ''; + var allmapidxlist = document.cumulativesettings.allmapidx.value; + if ((allmapidxlist != '') && (allmapidxlist != null)) { + var allmapidxs = allmapidxlist.split(','); + for (var i=0; i<allmapidxs.length; i++) { + var randompick = document.getElementById('randompick_'+allmapidxs[i]); + var rpicknum = document.getElementById('rpicknum_'+allmapidxs[i]); + var randorder = document.getElementById('randomorder_'+allmapidxs[i]); + if ((randompick.checked) && (rpicknum.value != '')) { + form.allrandompick.value += allmapidxs[i]+':'+rpicknum.value+','; + } + if (randorder.checked) { + form.allrandomorder.value += allmapidxs[i]+','; + } + } + form.allrandompick.value = form.allrandompick.value.replace(patt,""); + form.allrandomorder.value = form.allrandomorder.value.replace(patt,""); + } + if (document.cumulativesettings.currhiddenresource.value != form.allhiddenresource.value) { + haschanges = 1; + } + if (document.cumulativesettings.currencrypturl.value != form.allencrypturl.value) { + haschanges = 1; + } + if (document.cumulativesettings.currrandomorder.value != form.allrandomorder.value) { + haschanges = 1; + } + if (document.cumulativesettings.currrandompick.value != form.allrandompick.value) { + haschanges = 1; + } + } + if (doactions == 1) { + if (numchanges > 0) { + if ((cutwarnings > 0) || (remwarnings > 0)) { + if (remwarnings > 0) { + if (!confirm('$lt{"p_rmr1"}\\n\\n$lt{"p_rmr3a"} '+remwarnings+' $lt{"p_rmr3b"}')) { + return false; + } + } + if (cutwarnings > 0) { + if (!confirm('$lt{"p_ctr1a"}\\n$lt{"p_ctr1b"}\\n\\n$lt{"p_ctr3a"} '+cutwarnings+' $lt{"p_ctr3b"}')) { + return false; + } + } + } + form.submit(); + return true; + } + } + if (dosettings == 1) { + if (haschanges == 1) { + form.submit(); + return true; + } + } + if ((dosettings == 1) && (doactions == 1)) { + alert("$lt{'noor'}"); + } else { + if (dosettings == 1) { + alert("$lt{'noch'}"); + } else { + alert("$lt{'noac'}"); + } + } + return false; +} + +function setClass(value) { + var cutclass = 'LC_docs_cut'; + var copyclass = 'LC_docs_copy'; + var removeclass = 'LC_docs_remove'; + var cutreg = new RegExp("\\\\b"+cutclass+"\\\\b"); + var copyreg = new RegExp("\\\\b"+copyclass+"\\\\b"); + var removereg = new RegExp("\\\\"+removeclass+"\\\\b"); + var links = document.getElementsByTagName('a'); + for (var i=0; i<links.length; i++) { + var classes = links[i].className; + if (cutreg.test(classes)) { + links[i].className = cutclass; + if (value == 1) { + links[i].className += " LC_menubuttons_link"; + } + } else { + if (copyreg.test(classes)) { + links[i].className = copyclass; + if (value == 1) { + links[i].className += " LC_menubuttons_link"; + } + } else { + if (removereg.test(classes)) { + links[i].className = removeclass; + if (value == 1) { + links[i].className += " LC_menubuttons_link"; + } + } + } + } + } + return; +} + +function setBoxes(value) { + var remidxlist = document.cumulativeactions.allremoveidx.value; + if ((remidxlist != '') && (remidxlist != null)) { + var remidxs = remidxlist.split(','); + for (var i=0; i<remidxs.length; i++) { + if (document.getElementById('remove_'+remidxs[i])) { + var item = document.getElementById('remove_'+remidxs[i]); + if (value == 1) { + item.className = 'LC_docs_remove'; + } else { + item.className = 'LC_hidden'; + } + } + } + } + var cutidxlist = document.cumulativeactions.allcutidx.value; + if ((cutidxlist != '') && (cutidxlist != null)) { + var cutidxs = cutidxlist.split(','); + for (var i=0; i<cutidxs.length; i++) { + if (document.getElementById('cut_'+cutidxs[i])) { + var item = document.getElementById('cut_'+cutidxs[i]); + if (value == 1) { + item.className = 'LC_docs_cut'; + } else { + item.className = 'LC_hidden'; + } + } + } + } + var copyidxlist = document.cumulativeactions.allcopyidx.value; + if ((copyidxlist != '') && (copyidxlist != null)) { + var copyidxs = copyidxlist.split(','); + for (var i=0; i<copyidxs.length; i++) { + if (document.getElementById('copy_'+copyidxs[i])) { + var item = document.getElementById('copy_'+copyidxs[i]); + if (value == 1) { + item.className = 'LC_docs_copy'; + } else { + item.className = 'LC_hidden'; + } + } + } + } + return; } ENDNEWSCRIPT } + +sub history_tab_js { + return <<"ENDHIST"; +function toggleHistoryDisp(choice) { + document.docslogform.docslog.value = choice; + document.docslogform.submit(); + return; +} + +ENDHIST +} + +sub inject_data_js { + return <<ENDINJECT; + +function injectData(current, hiddenField, name, value) { + currentElement = document.getElementById(hiddenField); + currentElement.name = name; + currentElement.value = value; + current.submit(); +} + +ENDINJECT +} + +sub dump_switchserver_js { + my @hosts = @_; + my %lt = &Apache::lonlocal::texthash( + dump => 'Copying content to Authoring Space requires switching server.', + swit => 'Switch server?', + duco => 'Copying Content to Authoring Space', + yone => 'You need to switch to a server housing an Authoring Space for which you are author or co-author.', + chos => 'Choose server', + ); + my $role = $env{'request.role'}; + my $js = <<"ENDSWJS"; +<script type="text/javascript"> +function write_switchserver() { + var server; + if (document.setserver.posshosts.length > 0) { + for (var i=0; i<document.setserver.posshosts.length; i++) { + if (document.setserver.posshosts[i].checked) { + server = document.setserver.posshosts[i].value; + } + } + opener.document.location.href="/adm/switchserver?otherserver="+server+"&role=$role&origurl=/adm/coursedocs"; + } + window.close(); +} +</script> + +ENDSWJS + + my $startpage = &Apache::loncommon::start_page('Choose server',$js, + {'only_body' => 1, + 'js_ready' => 1,}); + my $endpage = &Apache::loncommon::end_page({'js_ready' => 1}); + + my $hostpicker; + my $count = 0; + foreach my $host (sort(@hosts)) { + my $checked; + if ($count == 0) { + $checked = ' checked="checked"'; + } + $hostpicker .= '<label><input type="radio" name="posshosts" value="'. + $host.'"'.$checked.' />'.$host.'</label> '; + $count++; + } + + return <<"ENDSWITCHJS"; + +function dump_needs_switchserver(url) { + if (url!='' && url!= null) { + if (confirm("$lt{'dump'}\\n$lt{'swit'}")) { + go(url); + } + } + return; +} + +function choose_switchserver_window() { + newWindow = window.open('','ChooseServer','height=400,width=500,scrollbars=yes') + newWindow.document.open(); + newWindow.document.writeln('$startpage'); + newWindow.document.write('<h3>$lt{'duco'}<\\/h3>\\n'+ + '<p>$lt{'yone'}<\\/p>\\n'+ + '<div class="LC_left_float"><fieldset><legend>$lt{'chos'}<\\/legend>\\n'+ + '<form name="setserver" method="post" action="" \\/>\\n'+ + '$hostpicker\\n'+ + '<br \\/><br \\/>\\n'+ + '<input type="button" name="makeswitch" value="$lt{'swit'}" '+ + 'onclick="write_switchserver();" \\/>\\n'+ + '<\\/form><\\/fieldset><\\/div><br clear="all" \\/>\\n'); + newWindow.document.writeln('$endpage'); + newWindow.document.close(); + newWindow.focus(); +} + +ENDSWITCHJS +} + +sub makedocslogform { + my ($formelems,$docslog) = @_; + return <<"LOGSFORM"; + <form action="/adm/coursedocs" method="post" name="docslogform"> + <input type="hidden" name="docslog" value="$docslog" /> + $formelems + </form> +LOGSFORM +} + +sub makesimpleeditform { + my ($formelems) = @_; + return <<"SIMPFORM"; + <form name="simpleedit" method="post" action="/adm/coursedocs"> + <input type="hidden" name="importdetail" value="" /> + $formelems + </form> +SIMPFORM +} + 1; __END__ @@ -3896,37 +6827,12 @@ sets @resources - array with the resourc Return hash with valid author names -=item dumpbutton() - -Generate "dump" button - =item clean() =item dumpcourse() Actually dump course - -=item exportbutton() - - Generate "export" button - -=item exportcourse() - -=item create_ims_store() - -=item build_package() - -=item get_dependencies() - -=item process_content() - -=item replicate_content() - -=item extract_media() - -=item store_template() - =item group_import() Imports the given (name, url) resources into the course @@ -3944,6 +6850,24 @@ Generate "dump" button =item do_paste_from_buffer() +=item do_buffer_empty() + +=item clear_from_buffer() + +=item get_newmap_url() + +=item dbcopy() + +=item uniqueness_check() + +=item contained_map_check() + +=item url_paste_fixups() + +=item apply_fixups() + +=item copy_dependencies() + =item update_parameter() =item handle_edit_cmd() @@ -3956,8 +6880,6 @@ Generate "dump" button =item is_supplemental_title() -=item parse_supplemental_title() - =item entryline() =item tiehash() @@ -3986,6 +6908,48 @@ Check Versions Breadcrumbs for special functions +=item create_list_elements() + +=item create_form_ul() + +=item startContentScreen() + +=item endContentScreen() + +=item supplemental_base() + +=item embedded_form_elems() + +=item embedded_destination() + +=item return_to_editor() + +=item decompression_info() + +=item decompression_phase_one() + +=item decompression_phase_two() + +=item remove_archive() + +=item generate_admin_menu() + +=item generate_edit_table() + +=item editing_js() + +=item history_tab_js() + +=item inject_data_js() + +=item dump_switchserver_js() + +=item resize_scrollbox_js() + +=item makedocslogform() + +=item makesimpleeditform() + =back =cut