Diff for /loncom/interface/slotrequest.pm between versions 1.110 and 1.138

version 1.110, 2011/01/03 18:04:56 version 1.138, 2018/06/24 04:11:08
Line 37  use Apache::lonnet; Line 37  use Apache::lonnet;
 use Apache::lonnavmaps();  use Apache::lonnavmaps();
 use Date::Manip;  use Date::Manip;
 use lib '/home/httpd/lib/perl/';  use lib '/home/httpd/lib/perl/';
 use LONCAPA;  use LONCAPA qw(:DEFAULT :match);
   
 sub fail {  sub fail {
     my ($r,$code)=@_;      my ($r,$code)=@_;
Line 56  sub fail { Line 56  sub fail {
 }  }
   
 sub start_page {  sub start_page {
     my ($r,$title,$brcrum)=@_;      my ($r,$title,$brcrum,$js)=@_;
     my $args;      my $args;
     if (ref($brcrum) eq 'ARRAY') {      if (ref($brcrum) eq 'ARRAY') {
         $args = {bread_crumbs => $brcrum};          $args = {bread_crumbs => $brcrum};
     }      }
     $r->print(&Apache::loncommon::start_page($title,undef,$args));      if (($env{'form.requestattempt'}) || ($env{'form.command'} eq 'manageresv')) {
           my %loaditems = (
                              onload => 'javascript:uncheckSlotRadio();',
                           );
           if (ref($args) eq 'HASH') {
               $args->{'add_entries'} = \%loaditems;
           } else {
               $args = { 'add_entries' => \%loaditems };
           }
       }
       $r->print(&Apache::loncommon::start_page($title,$js,$args));
 }  }
   
 sub end_page {  sub end_page {
Line 69  sub end_page { Line 79  sub end_page {
     $r->print(&Apache::loncommon::end_page());      $r->print(&Apache::loncommon::end_page());
 }  }
   
   sub reservation_js {
       my ($slots,$consumed_uniqueperiods,$available,$got_slots,$symb) = @_;
       return unless ((ref($slots) eq 'HASH') && (ref($available) eq 'ARRAY'));
       my $toskip;
       if ($symb eq '') {
           $toskip = { symb => 1, };
       }
       my ($i,$j) = (0,0);
       my $js;
       foreach my $slot (sort
           { return $slots->{$a}->{'starttime'} <=> $slots->{$b}->{'starttime'} }
                       (keys(%{$slots})))  {
   
           next if (!&allowed_slot($slot,$slots->{$slot},$symb,$slots,
                                   $consumed_uniqueperiods,$toskip));
           $js .= "    slotstart[$i]='$slots->{$slot}->{'starttime'}';\n".
                  "    slotend[$i]='$slots->{$slot}->{'endtime'}';\n".
                  "    slotname[$i]='$slot';\n";
           if (($symb) && (ref($got_slots) eq 'ARRAY')) {
               if (grep(/^\Q$slot\E$/,@{$got_slots})) {
                   $js .= "    currslot[$j]='$slot';\n";
                   $j++;
               }
           }
           $i++;
           push(@{$available},$slot);
       }
       if ($j) {
           $js = "    var currslot = new Array($j);\n\n$js";
       }
       my %alerts = &Apache::lonlocal::texthash (
                                                   none    => 'No reservable time slots found',
                                                   invalid => 'Invalid date format',
                                                );
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function updateSlotDisplay(form,num,slotpickradio) {
       var slotstart = new Array($i);
       var slotend = new Array($i);
       var slotname = new Array($i);
   $js
   
       if (slotpickradio == 'all') {
           for (var i=0; i<$i; i++) {
               if (document.getElementById('LC_slotrow_'+num+'_'+slotname[i])) {
                   document.getElementById('LC_slotrow_'+num+'_'+slotname[i]).style.display = '';
               }
               if (document.getElementById('LC_slotsearch_'+num)) {
                   document.getElementById('LC_slotsearch_'+num).style.display = 'block';
               }
           }
       } else {
           if (slotpickradio == 'show') {
               for (var i=0; i<$i; i++) {
                   if (document.getElementById('LC_slotrow_'+num+'_'+slotname[i])) {
                       document.getElementById('LC_slotrow_'+num+'_'+slotname[i]).style.display = 'none';
                   }
               }
               for (var j=0; j<$j; j++) {
                   if (document.getElementById('LC_slotrow_'+num+'_'+currslot[j])) {
                       document.getElementById('LC_slotrow_'+num+'_'+currslot[j]).style.display = '';
                   }
               }
               if (document.getElementById('LC_slotsearch_'+num)) {
                   document.getElementById('LC_slotsearch_'+num).style.display = 'block';
               }
           } else {
               var numberRegExp = /^[0-9]+\$/;
               var startm = form.start_month.options[form.start_month.selectedIndex].value;
               var startd = form.start_day.value;
               startd=startd.trim();
               var starty = form.start_year.value;
               starty=starty.trim();
               var endm = form.end_month.options[form.end_month.selectedIndex].value;
               var endd = form.end_day.value;
               endd=endd.trim();
               var endy = form.end_year.value;
               endy=endy.trim();
               if (numberRegExp.test(endd) && numberRegExp.test(endy) && numberRegExp.test(startd) && numberRegExp.test(starty)) {
                   var startdate = startm+"/"+startd+"/"+starty;
                   var starttime = new Date(startdate).getTime();
                   starttime = starttime/1000;
                   var starth = form.start_hour.options[form.start_hour.selectedIndex].value;
                   if (numberRegExp.test(starth)) {
                       starth = parseInt(starth);
                       if (starth > 0 && starth <= 23) {
                           starttime += 3600 * starth;
                       }
                   }
                   var enddate = endm+"/"+endd+"/"+endy;
                   var endtime = new Date(enddate).getTime();
                   endtime = endtime/1000;
                   var endh = form.end_hour.options[form.end_hour.selectedIndex].value;
                   if (numberRegExp.test(endh)) {
                       endh = parseInt(endh);
                       if (endh > 0 && endh <= 23) {
                           endtime += 3600 * endh;
                       }
                   }
   
                   var shown = 0;
                   for (var i=0; i<$i; i++) {
                       if ((slotstart[i] >= starttime) && (slotend[i] <= endtime)) {
                           if (document.getElementById('LC_slotrow_'+num+'_'+slotname[i])) {
                               document.getElementById('LC_slotrow_'+num+'_'+slotname[i]).style.display = '';
                               shown ++;
                           }
                       } else {
                           if (document.getElementById('LC_slotrow_'+num+'_'+slotname[i])) {
                               document.getElementById('LC_slotrow_'+num+'_'+slotname[i]).style.display = 'none';
                           }
                       }
                   }
                   if (document.getElementById('LC_slotsearch_'+num)) {
                       if (shown) {
                           document.getElementById('LC_slotsearch_'+num).style.display = 'block';
                       } else {
                           document.getElementById('LC_slotsearch_'+num).style.display = 'none';
                       }
                   }
                   if (shown == 0) {
                       alert('$alerts{"none"}');
                   }
               } else {
                   alert('$alerts{"invalid"}');
               }
           }
       }
       return;
   }
   
   function toggleSlotDisplay(form,num) {
       if (form.slotpick.length) {
           for (var i=0; i<form.slotpick.length; i++) {
               if (form.slotpick[i].checked) {
                   var val = form.slotpick[i].value;
                   if (document.getElementById('LC_slotfilter_'+num)) {
                       document.getElementById('LC_slotsearch_'+num).style.display = 'none';
                       if (val == 'filter') {
                           document.getElementById('LC_slotfilter_'+num).style.display = 'block';
                       } else {
                           document.getElementById('LC_slotfilter_'+num).style.display = 'none';
                           if (val == 'all') {
                               updateSlotDisplay(form,num,val);
                           } else {
                               updateSlotDisplay(form,num,val);
                           }
                       }
                   }
                   break;
               }
           }
       }
       return false;
   }
   
   if (!document.getElementsByClassName) {
       function getElementsByClassName(node, classname) {
           var a = [];
           var re = new RegExp('(^| )'+classname+'( |$)');
           var els = node.getElementsByTagName("*");
           for(var i=0,j=els.length; i<j; i++)
               if(re.test(els[i].className))a.push(els[i]);
           return a;
       }
   }
   
   function uncheckSlotRadio() {
       var slotpicks;
       if (document.getElementsByClassName) {
           slotpicks = document.getElementsByClassName('LC_slotpick_radio');
       } else {
           slotpicks = getElementsByClassName(document.body,'LC_slotpick_radio');
       }
       if (slotpicks.length) {
           for (var i=0; i<slotpicks.length; i++) {
               slotpicks[i].checked = false;  
           }
       }
   }
   
   function toggleSlotMap(maprownum,rownum) {
       if (document.getElementById('arrow'+maprownum)) {
           var img = document.getElementById('arrow'+maprownum);
           var rowdisplay;
           var celldisplay = '';
           if (img.src.indexOf('arrow.open.gif')!=-1) {
               img.src = '/adm/lonIcons/arrow.closed.gif';
               rowdisplay = 'none';
           }
           else {
               img.src = '/adm/lonIcons/arrow.open.gif';
               rowdisplay = 'table-row';
               celldisplay = 'none';
           }
           var resrows;
           var maptext;
           if (document.getElementsByClassName) {
               resrows = document.getElementsByClassName('LC_slotresrow_'+maprownum);
               maptext = document.getElementsByClassName('LC_slotmaptext_'+maprownum);
           } else {
               resrows = getElementsByClassName(document.body,'LC_slotresrow_'+maprownum);
               maptext = getElementsByClassName(document.body,'LC_slotmaptext_'+maprownum);
           }
           if (maptext.length) {
               for (var i=0; i<maptext.length; i++) {
                   maptext[i].style.display = celldisplay;
               }
           }
           if (resrows.length) {
              var mapbgidx = 0;
              var rowclasses = ['LC_even_row','LC_odd_row'];
              var mapbgClass = 'LC_even_row';
              var regExpBg = /LC_odd_row/i;
              if (rowdisplay == 'table-row') {
                   if (document.getElementById('LC_slotmaprow_'+rownum)) {
                       mapbgClass = document.getElementById('LC_slotmaprow_'+rownum).className;
                       if (regExpBg.test(mapbgClass)) {
                           mapbgidx = 1;
                       }
                   }
               }
               for (var i=0; i<resrows.length; i++) {
                   resrows[i].style.display = rowdisplay;
                   if (rowdisplay == 'table-row') {
                       mapbgidx ++;        
                       var bgcolnew = mapbgidx % 2;
                       var bgcolold = (mapbgidx+1) % 2;
                       var k = i+parseInt(rownum)+1; 
                       if (document.getElementById('LC_slotresrow_'+k)) {
                           document.getElementById('LC_slotresrow_'+k).className = document.getElementById('LC_slotresrow_'+k).className.replace(rowclasses[bgcolold],rowclasses[bgcolnew]);
                       }
                   }
               }
               if (document.getElementById('LC_slot_reservations')) {
                   var numrowsOdd = resrows.length % 2;
                   if (numrowsOdd) {
                       var lastbgClass = 'LC_even_row';
                       var idx = 0;
                       var lastresnum = parseInt(rownum) + resrows.length; 
                       if (rowdisplay == 'none') {
                           lastresnum = rownum;
                           if (document.getElementById('LC_slotmaprow_'+rownum)) {
                               lastbgClass = document.getElementById('LC_slotmaprow_'+rownum).className;
                           }
                       } else {
                           lastresnum = parseInt(rownum) + resrows.length;
                           if (document.getElementById('LC_slotresrow_'+lastresnum)) {
                               lastbgClass = document.getElementById('LC_slotresrow_'+lastresnum).className;
                           }
                       }
                       if (regExpBg.test(lastbgClass)) {
                           idx = 1;
                       }
                       var table = document.getElementById('LC_slot_reservations');
                       if ((table.rows.length) && (table.rows.length >= lastresnum)) {
                           for (var i=lastresnum; i<table.rows.length; i++) {
                               if (table.rows[i].style.display != 'none') {
                                   idx ++;
                                   var bgcolnew = idx % 2;
                                   var bgcolold = (idx+1) % 2;  
                                   j = i+1;
                                   if (document.getElementById('LC_slotmaprow_'+j)) {
                                       document.getElementById('LC_slotmaprow_'+j).className = rowclasses[bgcolnew];
                                   } else {
                                       if (document.getElementById('LC_slotresrow_'+j)) {
                                           document.getElementById('LC_slotresrow_'+j).className = document.getElementById('LC_slotresrow_'+j).className.replace(rowclasses[bgcolold],rowclasses[bgcolnew]);
                                       }
                                   }
                               }
                           }
                       }
                   }
               }
           }
       }
   }
   // ]]>
   </script>
   ENDSCRIPT
   
   }
   
   
 =pod  =pod
   
  slot_reservations db   slot_reservations db
Line 121  sub check_for_reservation { Line 416  sub check_for_reservation {
     my ($symb,$mode)=@_;      my ($symb,$mode)=@_;
     my $student = &Apache::lonnet::EXT("resource.0.availablestudent", $symb,      my $student = &Apache::lonnet::EXT("resource.0.availablestudent", $symb,
        $env{'user.domain'}, $env{'user.name'});         $env{'user.domain'}, $env{'user.name'});
   
     my $course = &Apache::lonnet::EXT("resource.0.available", $symb,      my $course = &Apache::lonnet::EXT("resource.0.available", $symb,
     $env{'user.domain'}, $env{'user.name'});      $env{'user.domain'}, $env{'user.name'});
     my @slots = (split(/:/,$student), split(/:/, $course));      my @slots = (split(/:/,$student), split(/:/, $course));
Line 137  sub check_for_reservation { Line 431  sub check_for_reservation {
  return 'error: Unable to determine current status';   return 'error: Unable to determine current status';
     }          }    
     my @got;      my @got;
     my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots);      my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots,'starttime');
     foreach my $slot_name (@sorted_slots) {      foreach my $slot_name (@sorted_slots) {
  next if (!defined($slots{$slot_name}) ||   next if (!defined($slots{$slot_name}) ||
  !ref($slots{$slot_name}));   !ref($slots{$slot_name}));
  &Apache::lonxml::debug(time." $slot_name ".   &Apache::lonxml::debug(time." $slot_name ".
        $slots{$slot_name}->{'starttime'}." -- ".         $slots{$slot_name}->{'starttime'}." -- ".
        $slots{$slot_name}->{'startreserve'});         $slots{$slot_name}->{'startreserve'}." -- ".
  if ($slots{$slot_name}->{'endtime'} > time &&                                 $slots{$slot_name}->{'endreserve'});
     $slots{$slot_name}->{'startreserve'} < time) {   if (($slots{$slot_name}->{'endtime'} > time) &&
     # between start of reservation times and end of slot      ($slots{$slot_name}->{'startreserve'} < time) &&
               ((!$slots{$slot_name}->{'endreserve'}) || 
                ($slots{$slot_name}->{'endreserve'} > time))) {
       # between start of reservation time and end of reservation time
               # and before end of slot
     if ($mode eq 'allslots') {      if ($mode eq 'allslots') {
  push(@got,$slot_name);   push(@got,$slot_name);
     } else {      } else {
Line 167  sub get_consumed_uniqueperiods { Line 465  sub get_consumed_uniqueperiods {
         return 'error: Unable to determine current status';          return 'error: Unable to determine current status';
     }      }
     my @problems = $navmap->retrieveResources(undef,      my @problems = $navmap->retrieveResources(undef,
       sub { $_[0]->is_problem() },1,0);        sub { $_[0]->is_problem() || $_[0]->is_tool() },1,0);
     my %used_slots;      my %used_slots;
     foreach my $problem (@problems) {      foreach my $problem (@problems) {
  my $symb = $problem->symb();   my $symb = $problem->symb();
Line 214  sub check_for_conflict { Line 512  sub check_for_conflict {
     if (!defined($new_slot->{'uniqueperiod'})) { return undef; }      if (!defined($new_slot->{'uniqueperiod'})) { return undef; }
   
     if (!ref($consumed_uniqueperiods)) {      if (!ref($consumed_uniqueperiods)) {
  $consumed_uniqueperiods = &get_consumed_uniqueperiods($slots);          if ($consumed_uniqueperiods =~ /^error: /) {
         if (ref($consumed_uniqueperiods) eq 'HASH') {              return $consumed_uniqueperiods;
     if (&Apache::lonnet::error(%$consumed_uniqueperiods)) {  
         return 'error: Unable to determine current status';  
     }  
         } else {          } else {
             return 'error: Unable to determine current status';      $consumed_uniqueperiods = &get_consumed_uniqueperiods($slots);
               if (ref($consumed_uniqueperiods) eq 'HASH') {
           if (&Apache::lonnet::error(%$consumed_uniqueperiods)) {
               return 'error: Unable to determine current status';
           }
               } else {
                   return 'error: Unable to determine current status';
               }
         }          }
     }      } 
       
     my ($new_uniq_start,$new_uniq_end) = @{$new_slot->{'uniqueperiod'}};      my ($new_uniq_start,$new_uniq_end) = @{$new_slot->{'uniqueperiod'}};
     foreach my $slot_name (keys(%$consumed_uniqueperiods)) {      foreach my $slot_name (keys(%$consumed_uniqueperiods)) {
  my ($start,$end)=@{$consumed_uniqueperiods->{$slot_name}};   my ($start,$end)=@{$consumed_uniqueperiods->{$slot_name}};
Line 335  sub store_slot_parm { Line 636  sub store_slot_parm {
                        context => $env{'form.context'},                         context => $env{'form.context'},
                     );                      );
   
     &Apache::lonnet::instructor_log('slotreservationslog',\%storehash,      &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
                                     '',$env{'user.name'},$env{'user.domain'},                                 '',$env{'user.name'},$env{'user.domain'},
                                     $cnum,$cdom);                                 $cnum,$cdom);
     &Apache::lonnet::instructor_log($cdom.'_'.$cnum.'_slotlog',\%storehash,      &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
                                     1,$env{'user.name'},$env{'user.domain'},                                 1,$env{'user.name'},$env{'user.domain'},
                                     $env{'user.name'},$env{'user.domain'});                                 $env{'user.name'},$env{'user.domain'});
   
     return;      return;
 }  }
Line 500  sub release_reservation { Line 801  sub release_reservation {
         return (0,'error: Unable to determine current status');          return (0,'error: Unable to determine current status');
     }      }
     my $passed_resource = $navmap->getBySymb($symb);      my $passed_resource = $navmap->getBySymb($symb);
     if ($passed_resource->is_map()) {      if (ref($passed_resource)) {
  my ($a_resource) =           if ($passed_resource->is_map()) {
     $navmap->retrieveResources($passed_resource,       my ($a_resource) = 
        sub {$_[0]->is_problem()},0,1);                  $navmap->retrieveResources($passed_resource, 
  $symb = $a_resource->symb();                                             sub {$_[0]->is_problem() || $_[0]->is_tool() },0,1);
               $symb = $a_resource->symb();
           }
       } else {
           unless ($mgr eq 'F') {
               return (0,'error: Unable to determine current status');
           }
     }      }
   
     # get parameter string, check for existance, rebuild string with the slot      # get parameter string, check for existence, rebuild string with the slot
     my $student = &Apache::lonnet::EXT("resource.0.availablestudent",      my $student = &Apache::lonnet::EXT("resource.0.availablestudent",
                                        $symb,$udom,$uname);                                         $symb,$udom,$uname);
     my @slots = split(/:/,$student);      my @slots = split(/:/,$student);
Line 534  sub release_reservation { Line 841  sub release_reservation {
                                action  => 'release',                                 action  => 'release',
                                context => $env{'form.context'},                                 context => $env{'form.context'},
                         );                          );
             &Apache::lonnet::instructor_log('slotreservationslog',\%storehash,              &Apache::lonnet::write_log('slotreservationslog',\%storehash,
                                             1,$uname,$udom,$cnum,$cdom);                                         1,$uname,$udom,$cnum,$cdom);
             &Apache::lonnet::instructor_log($cdom.'_'.$cnum.'_slotlog',\%storehash,              &Apache::lonnet::write_log($cdom.'_'.$cnum.'_slotlog',\%storehash,
                                             1,$uname,$udom,$uname,$udom);                                         1,$uname,$udom,$uname,$udom);
  }   }
     }      }
   
Line 631  sub get_slot { Line 938  sub get_slot {
     if ($slot_name && $slot_name ne $conflictable_slot) {      if ($slot_name && $slot_name ne $conflictable_slot) {
  my %slot=&Apache::lonnet::get_slot($slot_name);   my %slot=&Apache::lonnet::get_slot($slot_name);
  my $description1=&get_description($slot_name,\%slot);   my $description1=&get_description($slot_name,\%slot);
           my $slottype1=$slot{'type'};
  %slot=&Apache::lonnet::get_slot($env{'form.slotname'});   %slot=&Apache::lonnet::get_slot($env{'form.slotname'});
  my $description2=&get_description($env{'form.slotname'},\%slot);   my $description2=&get_description($env{'form.slotname'},\%slot);
  if ($slot_name ne $env{'form.slotname'}) {          if ($slottype1 eq 'preassigned') {
               $r->print('<p>'.&mt('You already have a reservation: "[_1]", assigned by your instructor.',
                                   $description1).'</p>'.
                         '<p>'.&mt('Your instructor must unassign it before you can make a new reservation.').
                         '</p>');
           } elsif ($slot_name ne $env{'form.slotname'}) {
     $r->print(<<STUFF);      $r->print(<<STUFF);
 <form method="post" action="/adm/slotrequest">  <form method="post" action="/adm/slotrequest">
    <input type="hidden" name="symb" value="$env{'form.symb'}" />     <input type="hidden" name="symb" value="$env{'form.symb'}" />
Line 692  STUFF Line 1005  STUFF
     }      }
   
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         'request' => 'Availibility list',          'request' => 'Availability list',
         'try'     => 'Try again?',          'try'     => 'Try again?',
         'or'      => 'or',          'or'      => 'or',
     );      );
Line 731  STUFF Line 1044  STUFF
 }  }
   
 sub allowed_slot {  sub allowed_slot {
     my ($slot_name,$slot,$symb,$slots,$consumed_uniqueperiods)=@_;      my ($slot_name,$slot,$symb,$slots,$consumed_uniqueperiods,$toskip)=@_;
   
     #already started      #already started
     if ($slot->{'starttime'} < time) {      if ($slot->{'starttime'} < time) {
Line 756  sub allowed_slot { Line 1069  sub allowed_slot {
     if ($slot->{'startreserve'} > time) {      if ($slot->{'startreserve'} > time) {
  return 0;   return 0;
     }      }
       # reserve time ended
       if (($slot->{'endreserve'}) &&
           ($slot->{'endreserve'} < time)) {
           return 0;
       }    
     &Apache::lonxml::debug("$slot_name reserve good");      &Apache::lonxml::debug("$slot_name reserve good");
   
     my $userallowed=0;      my $userallowed=0;
Line 800  sub allowed_slot { Line 1118  sub allowed_slot {
     return 0 if (!$userallowed);      return 0 if (!$userallowed);
   
     # not allowed for this resource      # not allowed for this resource
     if (defined($slot->{'symb'})      if (defined($slot->{'symb'})) {
  && $slot->{'symb'} ne $symb) {          my $exclude = 1;
  return 0;          my @symbs;
           if ($slot->{'symb'} =~ /,/) {
               @symbs = split(/\s*,\s*/,$slot->{'symb'});
           } else {
               @symbs = ($slot->{'symb'});
           }
           my ($map,$id,$url) = &Apache::lonnet::decode_symb($symb);
           foreach my $reqsymb (@symbs) {
               next if ($reqsymb eq '');
               my ($slotmap,$slotid,$sloturl) = &Apache::lonnet::decode_symb($reqsymb);
               if ($sloturl=~/\.(page|sequence)$/) {
                   if (($map ne '') && ($map eq $sloturl)) {
                       $exclude = 0;
                       last;
                   }
               } elsif ($reqsymb eq $symb) {
                   $exclude = 0;
                   last;
               }
           }
           if ($exclude) {
               unless ((ref($toskip) eq 'HASH') && ($toskip->{'symb'})) {
           return 0;
               }
           }
     }      }
   
     my $conflict = &check_for_conflict($symb,$slot_name,$slot,$slots,      my $conflict = &check_for_conflict($symb,$slot_name,$slot,$slots,
Line 830  sub get_description { Line 1172  sub get_description {
 }  }
   
 sub show_choices {  sub show_choices {
     my ($r,$symb,$formname)=@_;      my ($symb,$formname,$num,$class,$slots,$consumed_uniqueperiods,$available,$got_slots)=@_;
       my $output;
     my ($cnum,$cdom)=&get_course();  
     my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum);  
     my $consumed_uniqueperiods = &get_consumed_uniqueperiods(\%slots);  
     if (ref($consumed_uniqueperiods) eq 'HASH') {  
         if (&Apache::lonnet::error(%$consumed_uniqueperiods)) {  
             $r->print('<span class="LC_error">'.  
                       &mt('An error occurred determining slot availability').  
                       '</span>');  
             return;  
         }  
     } elsif ($consumed_uniqueperiods =~ /^error: /) {  
         $r->print('<span class="LC_error">'.  
                   &mt('An error occurred determining slot availability').  
                   '</span>');  
         return;  
     }  
     my (@available,$output);  
     &Apache::lonxml::debug("Checking Slots");      &Apache::lonxml::debug("Checking Slots");
     my @got_slots=&check_for_reservation($symb,'allslots');      if (!ref($available) eq 'ARRAY') {
     if ($got_slots[0] =~ /^error: /) {  
         $r->print('<span class="LC_error">'.  
                   &mt('An error occurred determining slot availability').  
                   '</span>');  
         return;          return;
     }      }
     foreach my $slot (sort       if (!@{$available}) {
       { return $slots{$a}->{'starttime'} <=> $slots{$b}->{'starttime'} }          $output = '<span class="LC_info">'.&mt('No available times.').'</span>';
       (keys(%slots)))  {  
   
  &Apache::lonxml::debug("Checking Slot $slot");  
  next if (!&allowed_slot($slot,$slots{$slot},$symb,\%slots,  
  $consumed_uniqueperiods));  
   
         push(@available,$slot);  
     }  
     if (!@available) {  
         $output = &mt('No available times.');  
         if ($env{'form.command'} ne 'manageresv') {          if ($env{'form.command'} ne 'manageresv') {
             $output .= ' <a href="/adm/flip?postdata=return:">'.              $output .= ' <a href="/adm/flip?postdata=return:">'.
                        &mt('Return to last resource').'</a>';                         &mt('Return to last resource').'</a>';
         }          }
         $r->print($output);          if ($class) {
         return;              return '<div class="'.$class.'">'.$output.'</div>';
           } else {
               return $output;
           }
       }
       if (@{$available} > 1) {
           my $numavailable = scalar(@{$available});
           my $numreserved = 0;
           my $js;
           my $j = 0;
           foreach my $got (@{$got_slots}) {
               unless (($got eq '') || (!defined($got))) {
                   $numreserved ++;
                   if ($env{'form.command'} eq 'manageresv') {
                       $js .= "    currslot[$j]='$got';\n";
                       $j++;
                   }
               }
           }
           my $showfilter = 'none';
           $output .= '<fieldset><legend>'.&mt('Actions').'</legend>'."\n".
                      '<form method="post" name="reservationdisplay_'.$num.
                      '" action="" onsubmit="toggleSlotDisplay(this.form,'."'$num'".');">';
           my @options = ('all','filter');
           if ($numreserved) {
               unshift(@options,'show');
           }
           my %resmenu = &Apache::lonlocal::texthash (
                                            show   => 'Show current reservation',
                                            all    => 'Show all', 
                                            filter => 'Search by date',
                        );
           foreach my $option (@options) {
               my $onclick = "toggleSlotDisplay(this.form,'$num');";
               if (($option eq 'show') && ($env{'form.command'} eq 'manageresv')) {  
                   $onclick .= "currSlotDisplay$num(this.form,'$num');"; 
               }
               $output .= '<span class="LC_nobreak"><label>'.
                          '<input type="radio" class="LC_slotpick_radio" name="slotpick" value="'.
                          $option.'" onclick="'.$onclick.'" />'.
                          $resmenu{$option}.
                          '</label></span>'.('&nbsp;' x3)."\n";
           }
           $output .= '</form>';
           my $chooserform = 'reservationchooser_'.$num;
           my $starttime = $slots->{$available->[0]}->{'starttime'};
           my $endtime = $slots->{$available->[-1]}->{'starttime'};
           if ($env{'form.command'} eq 'manageresv') {
               $output .= <<"ENDSCRIPT";
   
   <script type="text/javascript">
   // <![CDATA[
   function currSlotDisplay$num() {
       var currslot = new Array($numreserved);
   $js    
       for (var j=0; j<$numreserved; j++) {
           if (document.getElementById('LC_slotrow_$num\_'+currslot[j])) {
               document.getElementById('LC_slotrow_$num\_'+currslot[j]).style.display = '';
           }
       }
   }
   // ]]>
   </script>
   
   ENDSCRIPT
           }
           $output .=
               '<div id="LC_slotfilter_'.$num.'" style="display:'.$showfilter.'">'.
               '<form method="post" name="'.$chooserform.'" action="">'.
               '<table><tr><td>'.&mt('Open after').'</td><td>'.
               &Apache::lonhtmlcommon::date_setter($chooserform,'start',$starttime,'','','','','','','',1,1).
               '</td></tr><tr><td>'.&mt('Closed before').'</td><td>'.
               &Apache::lonhtmlcommon::date_setter($chooserform,'end',$endtime,'','','','','','','',1,1).
               '</td></tr></table><br />'.
               '<input type="button" name="slotfilter" value="Search for reservable slots" onclick="updateSlotDisplay(this.form,'."'$num'".');" />'.
               '</form></div><div id="LC_slotsearch_'.$num.'" style="display:none"><hr />';
     }      }
     if ($env{'form.command'} eq 'manageresv') {      if ($env{'form.command'} eq 'manageresv') {
         $output = '<table border="0">';          $output .= '<table border="0">';
     } else {      } else {
         $output = &Apache::loncommon::start_data_table();          $output .= &Apache::loncommon::start_data_table();
     }      }
     foreach my $slot (@available) {       foreach my $slot (@{$available}) {
  my $description=&get_description($slot,$slots{$slot});   my $description=&get_description($slot,$slots->{$slot});
  my $form;   my $form;
  if ((grep(/^\Q$slot\E$/,@got_slots)) ||   if ((grep(/^\Q$slot\E$/,@{$got_slots})) ||
     &space_available($slot,$slots{$slot},$symb)) {      &space_available($slot,$slots->{$slot},$symb)) {
     my $text=&mt('Select');      my $text=&mt('Select');
     my $command='get';      my $command='get';
     if (grep(/^\Q$slot\E$/,@got_slots)) {      if (grep(/^\Q$slot\E$/,@{$got_slots})) {
  $text=&mt('Drop Reservation');   $text=&mt('Drop Reservation');
  $command='release';   $command='release';
     } else {      } else {
  my $conflict = &check_for_conflict($symb,$slot,$slots{$slot},   my $conflict = &check_for_conflict($symb,$slot,$slots->{$slot},
    \%slots,     $slots,$consumed_uniqueperiods);
    $consumed_uniqueperiods);  
                 if ($conflict) {                  if ($conflict) {
                     if ($conflict =~ /^error: /) {                      if ($conflict =~ /^error: /) {
                         $form = '<span class="LC_error">'.                          $form = '<span class="LC_error">'.
                                 &mt('Slot: [_1] has unknown status.',$description).                                   &mt('Slot: [_1] has unknown status.',$description).
                                 '</span>';                                   '</span>';
                     } else {                      } else {
         $text=&mt('Change Reservation');          $text=&mt('Change Reservation');
         $command='get';          $command='get';
Line 908  sub show_choices { Line 1293  sub show_choices {
     }      }
     my $escsymb=&escape($symb);      my $escsymb=&escape($symb);
             if (!$form) {              if (!$form) {
                   my $name;
                 if ($formname) {                  if ($formname) {
                     $formname = 'name="'.$formname.'" ';                       $name = 'name="'.$formname.'"';
                 }                  }
                 my $context = 'user';                  my $context = 'user';
                 if ($env{'form.command'} eq 'manageresv') {                  if ($env{'form.command'} eq 'manageresv') {
                     $context = 'usermanage';                      $context = 'usermanage';
                 }                  }
         $form=<<STUFF;          $form=<<STUFF;
    <form method="post" action="/adm/slotrequest" $formname>     <form method="post" action="/adm/slotrequest" $name>
      <input type="submit" name="Select" value="$text" />       <input type="submit" name="Select" value="$text" />
      <input type="hidden" name="symb" value="$escsymb" />       <input type="hidden" name="symb" value="$escsymb" />
      <input type="hidden" name="slotname" value="$slot" />       <input type="hidden" name="slotname" value="$slot" />
Line 929  STUFF Line 1315  STUFF
             $form = &mt('Unavailable');              $form = &mt('Unavailable');
         }          }
         if ($env{'form.command'} eq 'manageresv') {          if ($env{'form.command'} eq 'manageresv') {
             $output .= '<tr>';              $output .= '<tr id="LC_slotrow_'.$num.'_'.$slot.'" >';
         } else {          } else {
     $output .= &Apache::loncommon::start_data_table_row();      $output .= &Apache::loncommon::start_data_table_row('','LC_slotrow_'.$num.'_'.$slot);
         }          }
         $output .= "           $output .= " 
  <td>$form</td>   <td>$form</td>
Line 945  STUFF Line 1331  STUFF
     if ($env{'form.command'} eq 'manageresv') {      if ($env{'form.command'} eq 'manageresv') {
         $output .= '</table>';          $output .= '</table>';
     } else {      } else {
        $output .= &Apache::loncommon::end_data_table();          $output .= &Apache::loncommon::end_data_table();
       }
       if (@{$available} > 1) {
           $output .= '</div></fieldset>';
       }
       if ($class) {
           return '<div class="'.$class.'">'.$output.'</div>';
       } else {
           return $output;
     }      }
     $r->print($output);  
 }  }
   
 sub to_show {  sub to_show {
Line 1049  sub show_table { Line 1442  sub show_table {
     my $available;      my $available;
     if ($mgr eq 'F') {      if ($mgr eq 'F') {
     # FIXME: This line should be deleted once Slots uses breadcrumbs      # FIXME: This line should be deleted once Slots uses breadcrumbs
     $r->print(&Apache::loncommon::help_open_topic('Slot About', 'Help on slots'));      $r->print('<br />'.&Apache::loncommon::help_open_topic(
           'Slot About', &mt('Help on slots')));
   
  $r->print('<div>');   $r->print('<div>');
  $r->print('<form method="post" action="/adm/slotrequest">   $r->print('<form method="post" action="/adm/slotrequest">
Line 1065  sub show_table { Line 1459  sub show_table {
     }      }
   
     if (!keys(%slots)) {      if (!keys(%slots)) {
         if ($crstype eq 'Community') {          $r->print(
             $r->print('<div>'.&mt('No slots have been created in this community.').'</div>');              '<p class="LC_info">'
         } else {             .&mt('No slots have been created in this '.lc($crstype).'.')
             $r->print('<div>'.&mt('No slots have been created in this course.').'</div>');             .'</p>'
         }          );
         return;          return;
     }      }
           
Line 1096  sub show_table { Line 1490  sub show_table {
      'starttime'       => 'Start time',       'starttime'       => 'Start time',
      'endtime'         => 'End Time',       'endtime'         => 'End Time',
              'startreserve'    => 'Time students can start reserving',               'startreserve'    => 'Time students can start reserving',
                'endreserve'      => 'Time students can no longer reserve',
              'reservationmsg'  => 'Message triggered by reservation',               'reservationmsg'  => 'Message triggered by reservation',
      'secret'          => 'Secret Word',       'secret'          => 'Secret Word',
      'space'           => '# of students/max',       'space'           => '# of students/max',
      'ip'              => 'IP or DNS restrictions',       'ip'              => 'IP or DNS restrictions',
      'symb'            => 'Resource slot is restricted to.',       'symb'            => 'Resource(s)/Map(s) slot is restricted to.',
      'allowedsections' => 'Sections slot is restricted to.',       'allowedsections' => 'Sections slot is restricted to.',
      'allowedusers'    => 'Users slot is restricted to.',       'allowedusers'    => 'Users slot is restricted to.',
      'uniqueperiod'    => 'Period of time slot is unique',       'uniqueperiod'    => 'Period of time slot is unique',
      'scheduled'       => 'Scheduled Students',       'scheduled'       => 'Scheduled Students',
      'proctor'         => 'List of proctors');       'proctor'         => 'List of proctors',
        'iptied'          => 'Unique IP each student',);
     if ($crstype eq 'Community') {      if ($crstype eq 'Community') {
         $show_fields{'startreserve'} = &mt('Time members can start reserving');          $show_fields{'startreserve'} = &mt('Time members can start reserving');
           $show_fields{'endreserve'} = &mt('Time members can no longer reserve');
         $show_fields{'scheduled'} = &mt('Scheduled Members');          $show_fields{'scheduled'} = &mt('Scheduled Members');
     }      }
     my @show_order=('name','description','type','starttime','endtime',      my @show_order=('name','description','type','starttime','endtime',
     'startreserve','reservationmsg','secret','space','ip','symb',      'startreserve','endreserve','reservationmsg','secret','space',
     'allowedsections','allowedusers','uniqueperiod',      'ip','iptied','symb','allowedsections','allowedusers','uniqueperiod',
     'scheduled','proctor');      'scheduled','proctor');
     my @show =       my @show = 
  (exists($env{'form.show'})) ? &Apache::loncommon::get_env_multiple('form.show')   (exists($env{'form.show'})) ? &Apache::loncommon::get_env_multiple('form.show')
Line 1198  sub show_table { Line 1595  sub show_table {
            <td valign="top">             <td valign="top">
             <table>              <table>
               <tr>                <tr>
                 <td rowspan="2">Deleted slots:</td>                  <td rowspan="2">'.&mt('Deleted slots:').'</td>
                 <td><label>'.$show_radio.'Show</label></td>                  <td><label>'.$show_radio.&mt('Show').'</label></td>
               </tr>                </tr>
               <tr>                <tr>
                 <td><label>'.$hide_radio.'Hide</label></td>                  <td><label>'.$hide_radio.&mt('Hide').'</label></td>
               </tr>                </tr>
             </table>              </table>
   </td>    </td>
Line 1211  sub show_table { Line 1608  sub show_table {
     $r->print('</div>');      $r->print('</div>');
     $r->print('<p><input type="submit" name="start" value="'.&mt('Update Display').'" /></p>');      $r->print('<p><input type="submit" name="start" value="'.&mt('Update Display').'" /></p>');
     my $linkstart='<a href="/adm/slotrequest?command=showslots&amp;order=';      my $linkstart='<a href="/adm/slotrequest?command=showslots&amp;order=';
     $r->print(&Apache::loncommon::start_data_table().      my $tableheader = &Apache::loncommon::start_data_table().
       &Apache::loncommon::start_data_table_header_row().'                &Apache::loncommon::start_data_table_header_row().'
        <th></th>');                <th></th>';
     foreach my $which (@show_order) {      foreach my $which (@show_order) {
  if ($which ne 'proctor' && exists($show{$which})) {   if ($which ne 'proctor' && exists($show{$which})) {
     $r->print('<th>'.$linkstart.$which.'">'.$show_fields{$which}.'</a></th>');      $tableheader .= '<th>'.$linkstart.$which.'">'.$show_fields{$which}.'</a></th>';
  }   }
     }      }
     $r->print(&Apache::loncommon::end_data_table_header_row());      $tableheader .= &Apache::loncommon::end_data_table_header_row();
       my $shownheader = 0;
   
     my %name_cache;      my %name_cache;
     my $slotsort = sub {      my $slotsort = sub {
  if ($env{'form.order'}=~/^(type|description|endtime|startreserve|ip|symb|allowedsections|allowedusers|reservationmsg)$/) {   if ($env{'form.order'}=~/^(type|description|endtime|startreserve|endreserve|ip|symb|allowedsections|allowedusers|reservationmsg)$/) {
     if (lc($slots{$a}->{$env{'form.order'}})      if (lc($slots{$a}->{$env{'form.order'}})
  ne lc($slots{$b}->{$env{'form.order'}})) {   ne lc($slots{$b}->{$env{'form.order'}})) {
  return (lc($slots{$a}->{$env{'form.order'}})    return (lc($slots{$a}->{$env{'form.order'}}) 
Line 1305  sub show_table { Line 1703  sub show_table {
  &Apache::lonlocal::locallocaltime($slots{$slot}->{'endtime'}):'');   &Apache::lonlocal::locallocaltime($slots{$slot}->{'endtime'}):'');
  my $start_reserve=($slots{$slot}->{'startreserve'}?   my $start_reserve=($slots{$slot}->{'startreserve'}?
    &Apache::lonlocal::locallocaltime($slots{$slot}->{'startreserve'}):'');     &Apache::lonlocal::locallocaltime($slots{$slot}->{'startreserve'}):'');
           my $end_reserve=($slots{$slot}->{'endreserve'}?
                            &Apache::lonlocal::locallocaltime($slots{$slot}->{'endreserve'}):'');
   
  my $unique;   my $unique;
  if (ref($slots{$slot}{'uniqueperiod'})) {   if (ref($slots{$slot}{'uniqueperiod'})) {
Line 1312  sub show_table { Line 1712  sub show_table {
  localtime($slots{$slot}{'uniqueperiod'}[1]);   localtime($slots{$slot}{'uniqueperiod'}[1]);
  }   }
   
  my $title;   my @titles;
  if (exists($slots{$slot}{'symb'})) {   if (exists($slots{$slot}{'symb'})) {
     my (undef,undef,$res)=              my @symbs;
  &Apache::lonnet::decode_symb($slots{$slot}{'symb'});              if ($slots{$slot}{'symb'} =~ /,/) {
     $res =   &Apache::lonnet::clutter($res);                  @symbs = split(/\s*,\s*/,$slots{$slot}{'symb'});
     $title = &Apache::lonnet::gettitle($slots{$slot}{'symb'});              } else {
     $title='<a href="'.$res.'?symb='.$slots{$slot}{'symb'}.'">'.$title.'</a>';                  @symbs = ($slots{$slot}{'symb'});
               }
               foreach my $reqsymb (@symbs) {
           my (undef,undef,$res) =
       &Apache::lonnet::decode_symb($reqsymb);
           $res = &Apache::lonnet::clutter($res);
           my $title = &Apache::lonnet::gettitle($reqsymb);
           push(@titles,'<a href="'.$res.'?symb='.$reqsymb.'">'.$title.'</a>');
               }
  }   }
   
  my $allowedsections;   my $allowedsections;
Line 1366  sub show_table { Line 1774  sub show_table {
                                                delete => 'Delete',                                                 delete => 'Delete',
                                                slotlog => 'History',                                                 slotlog => 'History',
         );          );
  my $edit=(<<"EDITLINK");          my ($edit,$delete,$showlog,$remove_all);
           if ($mgr) {
       $edit=(<<"EDITLINK");
 <a href="/adm/helper/newslot.helper?name=$slot">$lt{'edit'}</a>  <a href="/adm/helper/newslot.helper?name=$slot">$lt{'edit'}</a>
 EDITLINK  EDITLINK
   
  my $delete=(<<"DELETELINK");      $delete=(<<"DELETELINK");
 <a href="/adm/slotrequest?command=delete&amp;slotname=$slot">$lt{'delete'}</a>  <a href="/adm/slotrequest?command=delete&amp;slotname=$slot">$lt{'delete'}</a>
 DELETELINK  DELETELINK
   
         my $showlog=(<<"LOGLINK");              $remove_all=&remove_link($slot,'remove all').'<br />';
   
               if ($ids eq '') {
                   undef($remove_all);
               } else {
                   undef($delete);
               }
           }
   
           $showlog=(<<"LOGLINK");
 <a href="/adm/slotrequest?command=slotlog&amp;slotname=$slot">$lt{'slotlog'}</a>  <a href="/adm/slotrequest?command=slotlog&amp;slotname=$slot">$lt{'slotlog'}</a>
 LOGLINK  LOGLINK
   
         my $remove_all=&remove_link($slot,'remove all').'<br />';  
   
         if ($ids eq '') {  
             undef($remove_all);  
         } else {  
             undef($delete);  
         }  
  if ($slots{$slot}{'type'} ne 'schedulable_student') {   if ($slots{$slot}{'type'} ne 'schedulable_student') {
             undef($showlog);               undef($showlog); 
     undef($remove_all);      undef($remove_all);
  }   }
   
           unless ($shownheader) {
               $r->print($tableheader);
               $shownheader = 1;
           }
   
  my $row_start=&Apache::loncommon::start_data_table_row();   my $row_start=&Apache::loncommon::start_data_table_row();
  my $row_end=&Apache::loncommon::end_data_table_row();   my $row_end=&Apache::loncommon::end_data_table_row();
         $r->print($row_start.          $r->print($row_start.
Line 1412  LOGLINK Line 1829  LOGLINK
  if (exists($show{'startreserve'})) {   if (exists($show{'startreserve'})) {
     $colspan++;$r->print("<td>$start_reserve</td>\n");      $colspan++;$r->print("<td>$start_reserve</td>\n");
  }   }
           if (exists($show{'endreserve'})) {
               $colspan++;$r->print("<td>$end_reserve</td>\n");
           }
         if (exists($show{'reservationmsg'})) {          if (exists($show{'reservationmsg'})) {
             $colspan++;$r->print("<td>$reservemsg</td>\n");              $colspan++;$r->print("<td>$reservemsg</td>\n");
         }          }
Line 1431  LOGLINK Line 1851  LOGLINK
  if (exists($show{'ip'})) {   if (exists($show{'ip'})) {
     $colspan++;$r->print("<td>$slots{$slot}{'ip'}</td>\n");      $colspan++;$r->print("<td>$slots{$slot}{'ip'}</td>\n");
  }   }
           if (exists($show{'iptied'})) {
               $colspan++;
               if ($slots{$slot}{'iptied'} eq 'yes') {
                   $r->print('<td>'.&mt('Yes')."</td>\n");
               } elsif ($slots{$slot}{'iptied'} eq 'answer') {
                   $r->print('<td>'.&mt('Yes, including post-answer date')."</td>\n");
               } else {
                   $r->print('<td>'.&mt('No')."</td>\n");
               }
           }
  if (exists($show{'symb'})) {   if (exists($show{'symb'})) {
     $colspan++;$r->print("<td>$title</td>\n");      $colspan++;$r->print("<td>".join('<br />',@titles)."</td>\n");
  }   }
  if (exists($show{'allowedsections'})) {   if (exists($show{'allowedsections'})) {
     $colspan++;$r->print("<td>$allowedsections</td>\n");      $colspan++;$r->print("<td>$allowedsections</td>\n");
Line 1455  $row_end Line 1885  $row_end
 STUFF  STUFF
         }          }
     }      }
     $r->print(&Apache::loncommon::end_data_table().'</form>');      if ($shownheader) {
           $r->print(&Apache::loncommon::end_data_table());
       } else {
           $r->print('<p>'.&mt('No slots meet the criteria for display').'</p>');
       }
       $r->print('</form>');
     return;      return;
 }  }
   
 sub manage_reservations {  sub manage_reservations {
     my ($r,$crstype) = @_;      my ($r,$crstype,$slots,$consumed_uniqueperiods,$allavailable) = @_;
       my ($cnum,$cdom)=&get_course();
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
     $r->print('<p>'      $r->print('<p>'
              .&mt('Instructors may use a reservation system to place restrictions on when and where assignments can be worked on.')               .&mt('Instructors may use a reservation system to place restrictions on when and where assignments can be worked on.')
Line 1479  sub manage_reservations { Line 1915  sub manage_reservations {
         &Apache::lonnet::logthis('Manage Reservations - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});          &Apache::lonnet::logthis('Manage Reservations - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
         return;          return;
     }      }
     my (%parent,%shownparent,%container,%container_title,%contents);      if (ref($consumed_uniqueperiods) eq 'HASH') {
     my ($depth,$count,$reservable,$lastcontainer,$rownum) = (0,0,0,0,0);          if (&Apache::lonnet::error(%$consumed_uniqueperiods)) {
     my @backgrounds = ("LC_odd_row","LC_even_row");              $r->print('<span class="LC_error">'.
                         &mt('An error occurred determining slot availability.').
                         '</span>');
               return;
           }
       } elsif ($consumed_uniqueperiods =~ /^error: /) {
           $r->print('<span class="LC_error">'.
                     &mt('An error occurred determining slot availability.').
                     '</span>');
           return;
       }
       my (%output,%slotinfo,%statusbymap,%repsymbs,%shownmaps);
       my @possibles = $navmap->retrieveResources(undef,
                                                 sub { $_[0]->is_problem() || $_[0]->is_tool() },1,0);
   
       foreach my $resource (@possibles) {
           my ($useslots) = $resource->slot_control();
           next if (($useslots eq '') || ($useslots =~ /^\s*no\s*$/i));
           my $symb = $resource->symb();
           my ($slot_status,$date,$slot_name) = $resource->check_for_slot('0');
           my ($msg,$get_choices,$slotdescription);
           my $status = $resource->simpleStatus('0');
           my ($msg,$get_choices,$slotdescription);
           if ($slot_name ne '') {
               my %slot=&Apache::lonnet::get_slot($slot_name);
               $slotdescription=&get_description($slot_name,\%slot);
           }
           if ($slot_status == $resource->NOT_IN_A_SLOT) {
               $msg=&mt('No current reservation.');
               $get_choices = 1;
           } elsif ($slot_status == $resource->NEEDS_CHECKIN) {
               $msg='<span class="LC_nobreak">'.&mt('Reserved:').
                    '&nbsp;'.$slotdescription.'</span><br />'.
                    &mt('Access requires proctor validation.');
           } elsif ($slot_status == $resource->WAITING_FOR_GRADE) {
               $msg=&mt('Submitted and currently in grading queue.');
           } elsif ($slot_status == $resource->CORRECT) {
               $msg=&mt('Problem is unavailable.');
           } elsif ($slot_status == $resource->RESERVED) {
               $msg='<span class="LC_nobreak">'.&mt('Reserved:').
                    '&nbsp;'.$slotdescription.'</span><br />'.
                    &mt('Problem is currently available.');
           } elsif ($slot_status == $resource->RESERVED_LOCATION) {
               $msg='<span class="LC_nobreak">'.&mt('Reserved:').
                    '&nbsp;'.$slotdescription.'</span><br />'.
                    &mt('Problem is available at a different location.');
               $get_choices = 1;
           } elsif ($slot_status == $resource->RESERVED_LATER) {
               $msg='<span class="LC_nobreak">'.&mt('Reserved:').
                    '&nbsp;'.$slotdescription.'</span><br />'.
                    &mt('Problem will be available later.');
               $get_choices = 1;
           } elsif ($slot_status == $resource->RESERVABLE) {
               $msg=&mt('Reservation needed');
               $get_choices = 1;
           } elsif ($slot_status == $resource->RESERVABLE_LATER) {
               $msg=&mt('Reservation needed: will be reservable later.');
           } elsif ($slot_status == $resource->NOTRESERVABLE) {
               $msg=&mt('Reservation needed: none available.');
           } elsif ($slot_status == $resource->UNKNOWN) {
               $msg=&mt('Unable to determine status due to network problems.');
           } else {
               if ($status != $resource->OPEN) {
                   $msg = &Apache::lonnavmaps::getDescription($resource,'0');
               }
           }
           $output{$symb}{'msg'} = $msg;
           if (($status == $resource->OPEN) && ($get_choices)) {
               $output{$symb}{'hasaction'} = 1;
           }
           my ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($symb);
           $mapurl = &Apache::lonnet::clutter($mapurl);
           unless ($mapurl =~ /default\.sequence$/) {
               $shownmaps{$mapurl} = 1;
               my $map = $navmap->getResourceByUrl($mapurl);
               if (ref($map)) {
                   my @pcs = split(/,/,$map->map_hierarchy());
                   shift(@pcs);
                   shift(@pcs);
                   if (@pcs) {
                       map { $shownmaps{$navmap->getByMapPc($_)->src()} = 1; } reverse(@pcs);
                   }
               }
           }
           if (($useslots eq 'map_map') || ($useslots eq 'map')) {
               if ($slot_status ne '') {
                   if (ref($statusbymap{$mapurl}{$slot_status}) eq 'ARRAY') {
                       push(@{$statusbymap{$mapurl}{$slot_status}},$symb);
                   } else {
                       $statusbymap{$mapurl}{$slot_status} = [$symb];
                   }
               }
           }
       }
   
       foreach my $mapurl (keys(%statusbymap)) {
           if (ref($statusbymap{$mapurl}) eq 'HASH') {
               if (keys(%{$statusbymap{$mapurl}}) == 1) {
                   my @values = values(%{$statusbymap{$mapurl}});
                   my $repsymb = $values[0][0];
                   if (ref($output{$repsymb}) eq 'HASH') {
                       $output{$mapurl}{'msg'} = $output{$repsymb}{'msg'};
                       $output{$mapurl}{'hasaction'} = $output{$repsymb}{'hasaction'};
                   }
                   $repsymbs{$mapurl} = $repsymb;
               }
           }
       }
   
       my (%parent,%container,%container_title);
       my ($depth,$count,$reservable,$currcontainer,$rownum,$mapnum,$shown) = (0,0,0,0,0,0,0);
       my @backgrounds = ("LC_even_row","LC_odd_row");
     my $numcolors = scalar(@backgrounds);      my $numcolors = scalar(@backgrounds);
     my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace_21.gif");      my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace_21.gif");
     my $slotheader = '<p>'.      my $slotheader = '<p>'.
                  &mt('Your reservation status for any such assignments is listed below:').                   &mt('Your reservation status for any such assignments is listed below:').
                  '</p>'.                   '</p>'.
                  '<table class="LC_data_table LC_tableOfContent">'."\n";                   '<table class="LC_data_table LC_tableOfContent" id="LC_slot_reservations">'."\n";
     my $shownheader = 0;      my $shownheader = 0;
       my $currmap;
     my $it=$navmap->getIterator(undef,undef,undef,1,undef,undef);      my $it=$navmap->getIterator(undef,undef,undef,1,undef,undef);
     while (my $resource = $it->next()) {      while (my $resource = $it->next()) {
         if ($resource == $it->BEGIN_MAP()) {          if ($resource == $it->BEGIN_MAP()) {
             $depth++;              $depth++;
             $parent{$depth} = $lastcontainer;              $parent{$depth} = $currcontainer;
         }              if (ref($container{$currcontainer})) {
         if ($resource == $it->END_MAP()) {                  my $currmapres = $container{$currcontainer};
             $depth--;                  my $currmaptitle = $container_title{$currcontainer};
             $lastcontainer = $parent{$depth};                  $currmap = $currmapres->src();
         }                  my $currmaptype = 'sequence';
         if (ref($resource)) {                  if ($currmapres->is_page()) {
             my $symb = $resource->symb();                      $currmaptype = 'page';
             my $ressymb = $symb;  
             $contents{$lastcontainer} ++;  
             next if (!$resource->is_problem() && !$resource->is_sequence() &&   
                      !$resource->is_page());  
             $count ++;  
             if (($resource->is_sequence()) || ($resource->is_page())) {  
                 $lastcontainer = $count;  
                 $container{$lastcontainer} = $resource;  
                 $container_title{$lastcontainer} = $resource->compTitle();  
             }  
             if ($resource->is_problem()) {  
                 my ($useslots) = $resource->slot_control();  
                 next if (($useslots eq '') || ($useslots =~ /^\s*no\s*$/i));  
                 my ($msg,$get_choices,$slotdescription);  
                 my $title = $resource->compTitle();  
                 my $status = $resource->simpleStatus('0');  
                 my ($slot_status,$date,$slot_name) = $resource->check_for_slot('0');  
                 if ($slot_name ne '') {  
                     my %slot=&Apache::lonnet::get_slot($slot_name);  
                     $slotdescription=&get_description($slot_name,\%slot);  
                 }  
                 if ($slot_status == $resource->NOT_IN_A_SLOT) {  
                     $msg=&mt('No current reservation.');  
                     $get_choices = 1;  
                 } elsif ($slot_status == $resource->NEEDS_CHECKIN) {  
                     $msg='<span class="LC_nobreak">'.&mt('Reserved:').  
                          '&nbsp;'.$slotdescription.'</span><br />'.  
                          &mt('Access requires proctor validation.');  
                 } elsif ($slot_status == $resource->WAITING_FOR_GRADE) {  
                     $msg=&mt('Submitted and currently in grading queue.');  
                 } elsif ($slot_status == $resource->CORRECT) {  
                     $msg=&mt('Problem is unavailable.');  
                 } elsif ($slot_status == $resource->RESERVED) {  
                     $msg='<span class="LC_nobreak">'.&mt('Reserved:').  
                          '&nbsp;'.$slotdescription.'</span><br />'.  
                          &mt('Problem is currently available.');  
                 } elsif ($slot_status == $resource->RESERVED_LOCATION) {  
                     $msg='<span class="LC_nobreak">'.&mt('Reserved:').  
                          '&nbsp;'.$slotdescription.'</span><br />'.  
                          &mt('Problem is available at a different location.');  
                     $get_choices = 1;  
                 } elsif ($slot_status == $resource->RESERVED_LATER) {  
                     $msg='<span class="LC_nobreak">'.&mt('Reserved:').  
                          '&nbsp;'.$slotdescription.'</span><br />'.  
                          &mt('Problem will be available later.');  
                     $get_choices = 1;  
                 } elsif ($slot_status == $resource->RESERVABLE) {  
                     $msg=&mt('Reservation needed');  
                     $get_choices = 1;  
                 } elsif ($slot_status == $resource->NOTRESERVABLE) {  
                     $msg=&mt('Reservation needed: none available.');  
                 } elsif ($slot_status == $resource->UNKNOWN) {  
                     $msg=&mt('Unable to determine status due to network problems.');  
                 } else {  
                     if ($status != $resource->OPEN) {  
                         $msg = &Apache::lonnavmaps::getDescription($resource,'0');   
                     }  
                 }                  }
                 $reservable ++;                  if ($shownmaps{$currmap}) {
                 my $treelevel = $depth;                      $mapnum ++;
                 my $higherup = $lastcontainer;                      $rownum ++;
                 if ($depth > 1) {                      $shown ++;
                     my @maprows;                      if (!$shownheader) {
                     while ($treelevel > 1) {                          $r->print($slotheader);
                         if (ref($container{$higherup})) {                          $shownheader = 1;
                             my $res = $container{$higherup};  
                             last if (defined($shownparent{$higherup}));  
                             my $maptitle = $res->compTitle();  
                             my $type = 'sequence';  
                             if ($res->is_page()) {  
                                 $type = 'page';  
                             }  
                             &show_map_row($treelevel,$location,$type,$maptitle,  
                                           \@maprows);  
                             $shownparent{$higherup} = 1;  
                         }  
                         $treelevel --;  
                         $higherup = $parent{$treelevel};  
                     }                      }
                     foreach my $item (@maprows) {                      my $bgcolor = $backgrounds[$shown % $numcolors];
                         $rownum ++;                      my ($spacers,$icon);
                         my $bgcolor = $backgrounds[$rownum % $numcolors];                      my $row = '<tr class="'.$bgcolor.'" id="LC_slotmaprow_'.$rownum.'">';
                         if (!$shownheader) {                      if (ref($statusbymap{$currmap}) eq 'HASH') {
                             $r->print($slotheader);                          my ($spacers,$icon) = &show_map_row($depth-1,$location,$currmaptype,$currmaptitle);
                             $shownheader = 1;                          my $arrowstate = 'open';
                           if (keys(%{$statusbymap{$currmap}}) == 1) {
                               $arrowstate = 'closed';
                         }                          }
                         $r->print('<tr class="'.$bgcolor.'">'.$item.'</tr>'."\n");                          $row .= '<td>'.$spacers.'<img src="/adm/lonIcons/arrow.'.$arrowstate.'.gif" '.
                                   'id="arrow'.$mapnum.'" '.'alt="arrow" onmouseover="this.style.cursor=\'pointer\'" '.
                                   'onclick="'."toggleSlotMap('$mapnum','$rownum');".'" />'.
                                   $icon.('&nbsp;' x6).'</td>'."\n";
                           if (ref($output{$currmap}) eq 'HASH') {
                               my $formnum = $mapnum.'_'.$reservable+1;
                               my $class = 'LC_slotmaptext_'.$mapnum;
                               if ($output{$currmap}{'hasaction'}) {
                                   $row .= '<td valign="top"><span class="'.$class.'">'.
                                             $output{$currmap}{'msg'}.
                                             '</span></td><td valign="top">'.
                                             &slot_chooser($repsymbs{$currmap},$class,$formnum,
                                                           $allavailable,$slots,$consumed_uniqueperiods).
                                             '</td>';
                               } else {
                                   $row .= '<td colspan="2" valign="middle"><span class="'.$class.'">'.
                                             $output{$currmap}{'msg'}.
                                             '</span></td>';
                               }
                               $row .= '</tr>'."\n";
                           } else {
                               $row .= '<td colspan="2">&nbsp;</td></tr>'."\n";
                           }
                       } else {
                           my ($spacers,$icon) = &show_map_row($depth,$location,$currmaptype,$currmaptitle);
                           $row .= '<td>'.$spacers.$icon.('&nbsp;' x6).'</td><td colspan="2">&nbsp;</td></tr>'."\n";
                     }                      }
                       $r->print($row);
                 }                  }
               }
           } elsif ($resource == $it->END_MAP()) {
               $depth--;
               $currcontainer = $parent{$depth};
           } elsif (ref($resource)) {
               my $symb = $resource->symb();
               next if (!$resource->is_problem() && !$resource->is_tool() &&
                        !$resource->is_sequence() && !$resource->is_page());
               $count ++;
               if (($resource->is_sequence()) || ($resource->is_page())) {
                   $currcontainer = $count;
                   $container{$currcontainer} = $resource;
                   $container_title{$currcontainer} = $resource->compTitle();
               }
               if (($resource->is_problem() || $resource->is_tool)) {
                   next unless (exists($output{$symb}));
                   $reservable ++;
                 $rownum ++;                  $rownum ++;
                 my $bgcolor = $backgrounds[$rownum % $numcolors];  
                 if (!$shownheader) {                  if (!$shownheader) {
                     $r->print($slotheader);                      $r->print($slotheader);
                     $shownheader = 1;                      $shownheader = 1;
                 }                  }
                 $r->print('<tr class="'.$bgcolor.'"><td>'."\n");                  my $style;
                   if (exists($output{$currmap})) {
                       $style = 'none';
                   } else {
                       $style = 'table-row';
                       $shown ++;
                   }
                   my $title = $resource->compTitle();
                   my $bgcolor = $backgrounds[$shown % $numcolors];
                   $r->print('<tr class="'.$bgcolor.' LC_slotresrow_'.$mapnum.'"'.
                             ' style="display:'.$style.'" id="LC_slotresrow_'.$rownum.'">'.
                             '<td>');
                 for (my $i=0; $i<$depth; $i++) {                  for (my $i=0; $i<$depth; $i++) {
                     $r->print('<img src="'.$location.'" alt="" />');                      $r->print('<img src="'.$location.'" alt="" />');
                 }                  }
                 my $result = '<a href="'.$resource->src().'?symb='.$symb.'">'.                  $r->print('<a href="'.$resource->src().'?symb='.$symb.'">'.
                              '<img class="LC_contentImage" src="/adm/lonIcons/';                            '<img class="LC_contentImage" src="/adm/lonIcons/');
                 if ($resource->is_task()) {                  if ($resource->is_task()) {
                     $result .= 'task.gif" alt="'.&mt('Task');                      $r->print('task.gif" alt="'.&mt('Task'));
                   } elsif ($resource->is_tool()) {
                       $r->print('unknown.gif" alt="'.&mt('External Tool'));
                 } else {                  } else {
                     $result .= 'problem.gif" alt="'.&mt('Problem');                      $r->print('problem.gif" alt="'.&mt('Problem'));
                 }  
                 $result .= '" /><b>'.$title.'</b></a>'.('&nbsp;' x6).'</td>';  
                 my $hasaction;  
                 if ($status == $resource->OPEN) {  
                     if ($get_choices) {  
                         $hasaction = 1;  
                     }  
                 }                  }
                 if ($hasaction) {                  $r->print('" /><b>'.$title.'</b></a>'.('&nbsp;' x6).'</td>');
                     $result .= '<td valgn="middle">'.$msg.'</td>'.                  my $class = 'LC_slottext_'.$mapnum;
                                '<td valign="middle">'.('&nbsp;' x6);                  if ($output{$symb}{'hasaction'}) {
                       $r->print('<td valign="top"><span class="'.$class.'">'.$output{$symb}{'msg'}.'</span></td>'.
                                 '<td valign="top">'.
                                 &slot_chooser($symb,$class,$reservable,$allavailable,$slots,
                                               $consumed_uniqueperiods).'</td>');
                 } else {                  } else {
                     $result .= '<td colspan="2" valign="middle">'.$msg.'</td>';                      $r->print('<td colspan="2" valign="middle">'.
                                 '<span class="'.$class.'">'.$output{$symb}{'msg'}.'</span>'.
                                 '</td>');
                 }                  }
                 $r->print($result);                  $r->print('</tr>'."\n");
                 if ($hasaction) {  
                     my $formname = 'manageres_'.$reservable;  
                     &show_choices($r,$symb,$formname);  
                     $r->print('</td>');  
                 }  
                 $r->print('</tr>');  
             }              }
         }          }
     }      }
Line 1647  sub manage_reservations { Line 2175  sub manage_reservations {
 }  }
   
 sub show_map_row {  sub show_map_row {
     my ($depth,$location,$type,$title,$maprows) = @_;      my ($depth,$location,$type,$title) = @_;
     my $output = '<td>';      my $spacers;
     for (my $i=0; $i<$depth-1; $i++) {      for (my $i=0; $i<$depth-1; $i++) {
         $output .= '<img src="'.$location.'" alt="" />';          $spacers .= '<img src="'.$location.'" alt="" />';
     }      }
       my $icon;
     if ($type eq 'page') {      if ($type eq 'page') {
         $output .= '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />&nbsp;'."\n";          $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />&nbsp;'."\n";
     } else {      } else {
         $output .= '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />&nbsp;'."\n";          $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />&nbsp;'."\n";
     }      }
     $output .= $title.'</td><td colspan="2">&nbsp;</td>'."\n";      $icon .= $title;
     unshift (@{$maprows},$output);      return ($spacers,$icon);
     return;  }
   
   sub slot_chooser {
       my ($symb,$class,$formnum,$allavailable,$slots,$consumed_uniqueperiods) = @_;
       my $output;
       my @got_slots=&check_for_reservation($symb,'allslots');
       if ($got_slots[0] =~ /^error: /) {
           $output = '<span class="'.$class.'"><span class="LC_error">'.
                     &mt('An error occurred determining slot availability.').
                     '</span></span>';
       } else {
           my $formname = 'manageres_'.$formnum;
           if (ref($allavailable) eq 'ARRAY') {
               my @available;
               if (ref($slots) eq 'HASH') {
                   foreach my $slot (@{$allavailable}) {
                       # not allowed for this resource
                       if (ref($slots->{$slot}) eq 'HASH') {
                           if ($slots->{$slot}->{'symb'} ne '') {
                               my ($map,$id,$url) = &Apache::lonnet::decode_symb($symb);
                               my $exclude = 1;
                               my @reqsymbs = split(/\s*,\s*/,$slots->{$slot}->{'symb'});
                               if (@reqsymbs) {
                                   if (grep(/^\Q$symb\E$/,@reqsymbs)) {
                                       $exclude = 0;
                                   } else {
                                       foreach my $reqsymb (@reqsymbs) {
                                           my (undef,undef,$sloturl) = &Apache::lonnet::decode_symb($reqsymb);
                                           if ($sloturl=~/\.(page|sequence)$/) {
                                               if (($map ne '') && ($map eq $sloturl)) {
                                                   $exclude = 0;
                                                   last;
                                               }
                                           }
                                       }
                                   }
                                   next if ($exclude);   
                               }
                           }
                       }
                       push(@available,$slot);
                   }
               }
               $output .= &show_choices($symb,$formname,$formnum,$class,
                                        $slots,$consumed_uniqueperiods,
                                        \@available,\@got_slots);
           }
       }
       return $output;
 }  }
   
 sub show_reservations {  sub show_reservations {
Line 1671  sub show_reservations { Line 2248  sub show_reservations {
         $udom = $env{'user.domain'};          $udom = $env{'user.domain'};
     }      }
     my $formname = 'slotlog';      my $formname = 'slotlog';
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};      my ($cnum,$cdom)=&get_course();
     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};  
     my $crstype = &Apache::loncommon::course_type();      my $crstype = &Apache::loncommon::course_type();
     my %log=&Apache::lonnet::dump('nohist_'.$cdom.'_'.$cnum.'_slotlog',$udom,$uname);      my %log=&Apache::lonnet::dump('nohist_'.$cdom.'_'.$cnum.'_slotlog',$udom,$uname);
     if ($env{'form.origin'} eq 'aboutme') {      if ($env{'form.origin'} eq 'aboutme') {
Line 1773  sub show_reservations { Line 2349  sub show_reservations {
     if ($showntablehdr) {      if ($showntablehdr) {
         $r->print(&Apache::loncommon::end_data_table().'<br />');          $r->print(&Apache::loncommon::end_data_table().'<br />');
         if (($curr{'page'} > 1) || ($more_records)) {          if (($curr{'page'} > 1) || ($more_records)) {
             $r->print('<table><tr>');              $r->print('<p>');
             if ($curr{'page'} > 1) {              if ($curr{'page'} > 1) {
                 $r->print('<td><a href="javascript:chgPage('."'previous'".');">'.&mt('Previous [_1] changes',$curr{'show'}).'</a></td>');                  $r->print('<input type="button" onclick="javascript:chgPage('."'previous'".');" value="'.
                             &mt('Previous [_1] changes',$curr{'show'}).'" />');
             }              }
             if ($more_records) {              if ($more_records) {
                 $r->print('<td><a href="javascript:chgPage('."'next'".');">'.&mt('Next [_1] changes',$curr{'show'}).'</a></td>');                  $r->print('<input type="button" onclick="javascript:chgPage('."'next'".');" value="'.
                             &mt('Next [_1] changes',$curr{'show'}).'" />');
             }              }
             $r->print('</tr></table>');              $r->print('</p>');
             $r->print(<<"ENDSCRIPT");              $r->print(<<"ENDSCRIPT");
 <script type="text/javascript">  <script type="text/javascript">
   // <![CDATA[
 function chgPage(caller) {  function chgPage(caller) {
     if (caller == 'previous') {      if (caller == 'previous') {
         document.$formname.page.value --;          document.$formname.page.value --;
Line 1793  function chgPage(caller) { Line 2372  function chgPage(caller) {
     document.$formname.submit();      document.$formname.submit();
     return;      return;
 }  }
   // ]]>
 </script>  </script>
 ENDSCRIPT  ENDSCRIPT
         }          }
Line 1843  sub show_reservations_log { Line 2423  sub show_reservations_log {
         return;          return;
     }      }
     my $formname = 'reservationslog';      my $formname = 'reservationslog';
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};      my ($cnum,$cdom)=&get_course();
     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};  
     my %slotlog=&Apache::lonnet::dump('nohist_slotreservationslog',$cdom,$cnum);      my %slotlog=&Apache::lonnet::dump('nohist_slotreservationslog',$cdom,$cnum);
     if ((keys(%slotlog))[0]=~/^error\:/) { undef(%slotlog); }      if ((keys(%slotlog))[0]=~/^error\:/) { undef(%slotlog); }
   
Line 1982  sub show_reservations_log { Line 2561  sub show_reservations_log {
     if ($showntablehdr) {      if ($showntablehdr) {
         $r->print(&Apache::loncommon::end_data_table().'<br />');          $r->print(&Apache::loncommon::end_data_table().'<br />');
         if (($curr{'page'} > 1) || ($more_records)) {          if (($curr{'page'} > 1) || ($more_records)) {
             $r->print('<table><tr>');              $r->print('<p>');
             if ($curr{'page'} > 1) {              if ($curr{'page'} > 1) {
                 $r->print('<td><a href="javascript:chgPage('."'previous'".');">'.&mt('Previous [_1] changes',$curr{'show'}).'</a></td>');                  $r->print('<input type="button" onclick="javascript:chgPage('."'previous'".');" value="'.
                             &mt('Previous [_1] changes',$curr{'show'}).'" />');
             }              }
             if ($more_records) {              if ($more_records) {
                 $r->print('<td><a href="javascript:chgPage('."'next'".');">'.&mt('Next [_1] changes',$curr{'show'}).'</a></td>');                  $r->print('<input type="button" onclick="javascript:chgPage('."'next'".');" value="'.
                             &mt('Next [_1] changes',$curr{'show'}).'" />');
             }              }
             $r->print('</tr></table>');              $r->print('</p>');
             $r->print(<<"ENDSCRIPT");              $r->print(<<"ENDSCRIPT");
 <script type="text/javascript">  <script type="text/javascript">
 function chgPage(caller) {  function chgPage(caller) {
Line 2030  sub get_resource_title { Line 2611  sub get_resource_title {
                 $maptitle = $maptitles->{$mapurl};                  $maptitle = $maptitles->{$mapurl};
             } else {              } else {
                 if ($mapurl eq $env{'course.'.$env{'request.course.id'}.'.url'}) {                  if ($mapurl eq $env{'course.'.$env{'request.course.id'}.'.url'}) {
                     $maptitle=&mt('Main Course Documents');                      $maptitle=&mt('Main Content');
                 } else {                  } else {
                     $maptitle=&Apache::lonnet::gettitle($mapurl);                      $maptitle=&Apache::lonnet::gettitle($mapurl);
                 }                  }
Line 2129  sub display_filter { Line 2710  sub display_filter {
         }          }
         $output .= '</select></td>';          $output .= '</select></td>';
     }      }
     $output .= '<td>&nbsp;&nbsp;</td><td valign="middle"><input type="submit" value="'.      $output .= '<td>&nbsp;&nbsp;</td></tr></table>'.
                &mt('Update Display').'" /></tr></table>'.                 '<p><input type="submit" value="'.
                  &mt('Update Display').'" /></p>'.
                '<p class="LC_info">'.                 '<p class="LC_info">'.
                &mt('Only changes made from servers running LON-CAPA [_1] or later are displayed.'                 &mt('Only changes made from servers running LON-CAPA [_1] or later are displayed.'
                   ,'2.9.0');                    ,'2.9.0');
Line 2181  sub upload_start { Line 2763  sub upload_start {
     my ($r)=@_;          my ($r)=@_;    
     $r->print(      $r->print(
         &Apache::grades::checkforfile_js()          &Apache::grades::checkforfile_js()
        .'<h3>'.&mt('Specify a file containing the slot definitions.').'</h3>'         .'<h2>'.&mt('Upload a file containing the slot definitions').'</h2>'
        .'<form method="post" enctype="multipart/form-data"'         .'<form method="post" enctype="multipart/form-data"'
        .' action="/adm/slotrequest" name="slotupload">'         .' action="/adm/slotrequest" name="slotupload">'
        .'<input type="hidden" name="command" value="csvuploadmap" />'         .'<input type="hidden" name="command" value="csvuploadmap" />'
Line 2215  sub csvuploadmap_header { Line 2797  sub csvuploadmap_header {
   
     my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');      my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');
     my $ignore=&mt('Ignore First Line');      my $ignore=&mt('Ignore First Line');
  my $help_field = &Apache::loncommon::help_open_topic('Slot SelectingField');      my $buttontext = &mt('Reverse Association');
   
       $r->print(
           '<form method="post" enctype="multipart/form-data" action="/adm/slotrequest" name="slotupload">'
          .'<h2>'.&mt('Identify fields in uploaded list').'</h2>'
          .'<div class="LC_columnSection">'
          .&Apache::loncommon::help_open_topic(
               'Slot About',&mt('Help on slots'))
          .' '.&Apache::loncommon::help_open_topic(
               'Slot SelectingField',&mt('Help on selecting Fields'))
          ."</div>\n"
          .'<p class="LC_info">'
          .&mt('Total number of records found in file: [_1]','<b>'.$distotal.'</b>')
          ."</p>\n"
       );
       if ($distotal == 0) {
           $r->print('<p class="LC_warning">'.&mt('None found').'</p>');
       }
       $r->print(
           '<p>'
          .&mt('Enter as many fields as you can.').'<br />'
          .&mt('The system will inform you and bring you back to this page,[_1]if the data selected is insufficient to create the slots.','<br />')
          .'</p>'
       );
       $r->print(
           '<div class="LC_left_float">'
          .'<fieldset><legend>'.&mt('Functions').'</legend>'
          .'<label><input type="checkbox" name="noFirstLine"'.$checked.' />'.$ignore.'</label>'
          .' <input type="button" value="'.$buttontext
              .'" onclick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />'
          .'</fieldset></div><br clear="all" />'
       );
   
     $r->print(<<ENDPICK);      $r->print(<<ENDPICK);
 <form method="post" enctype="multipart/form-data" action="/adm/slotrequest" name="slotupload">  
 <h3>Identify fields $help_field</h3>  
 Total number of records found in file: $distotal <hr />  
 Enter as many fields as you can. The system will inform you and bring you back  
 to this page if the data selected is insufficient to create the slots.<hr />  
 <input type="button" value="Reverse Association" onclick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />  
 <label><input type="checkbox" name="noFirstLine"$checked />$ignore</label>  
 <input type="hidden" name="associate"  value="" />  <input type="hidden" name="associate"  value="" />
 <input type="hidden" name="datatoken"  value="$datatoken" />  <input type="hidden" name="datatoken"  value="$datatoken" />
 <input type="hidden" name="fileupload" value="$env{'form.fileupload'}" />  <input type="hidden" name="fileupload" value="$env{'form.fileupload'}" />
Line 2232  to this page if the data selected is ins Line 2838  to this page if the data selected is ins
 <input type="hidden" name="upfile_associate"   <input type="hidden" name="upfile_associate" 
                                        value="$env{'form.upfile_associate'}" />                                         value="$env{'form.upfile_associate'}" />
 <input type="hidden" name="command"    value="csvuploadassign" />  <input type="hidden" name="command"    value="csvuploadassign" />
 <hr />  
 <script type="text/javascript" language="Javascript">  <script type="text/javascript" language="Javascript">
   // <![CDATA[
 $javascript  $javascript
   // ]]>
 </script>  </script>
 ENDPICK  ENDPICK
     return '';      return '';
Line 2245  sub csvuploadmap_footer { Line 2852  sub csvuploadmap_footer {
     my ($request,$i,$keyfields) =@_;      my ($request,$i,$keyfields) =@_;
     my $buttontext = &mt('Create Slots');      my $buttontext = &mt('Create Slots');
     $request->print(<<ENDPICK);      $request->print(<<ENDPICK);
 </table>  
 <input type="hidden" name="nfields" value="$i" />  <input type="hidden" name="nfields" value="$i" />
 <input type="hidden" name="keyfields" value="$keyfields" />  <input type="hidden" name="keyfields" value="$keyfields" />
 <input type="button" onclick="javascript:verify(this.form)" value="$buttontext" /><br />  <input type="button" onclick="javascript:verify(this.form)" value="$buttontext" /><br />
Line 2254  ENDPICK Line 2860  ENDPICK
 }  }
   
 sub csvupload_javascript_reverse_associate {  sub csvupload_javascript_reverse_associate {
     my $error1=&mt('You need to specify the name, starttime, endtime and a type');      my $error1=&mt('You need to specify the name, start time, end time and a type.');
     return(<<ENDPICK);      return(<<ENDPICK);
   function verify(vf) {    function verify(vf) {
     var foundstart=0;      var foundstart=0;
Line 2280  ENDPICK Line 2886  ENDPICK
 }  }
   
 sub csvupload_javascript_forward_associate {  sub csvupload_javascript_forward_associate {
     my $error1=&mt('You need to specify the name, starttime, endtime and a type');      my $error1=&mt('You need to specify the name, start time, end time and a type.');
   return(<<ENDPICK);    return(<<ENDPICK);
   function verify(vf) {    function verify(vf) {
     var foundstart=0;      var foundstart=0;
Line 2312  sub csv_upload_map { Line 2918  sub csv_upload_map {
     if (!$env{'form.datatoken'}) {      if (!$env{'form.datatoken'}) {
  $datatoken=&Apache::loncommon::upfile_store($r);   $datatoken=&Apache::loncommon::upfile_store($r);
     } else {      } else {
  $datatoken=$env{'form.datatoken'};          $datatoken=&Apache::loncommon::valid_datatoken($env{'form.datatoken'});
  &Apache::loncommon::load_tmp_file($r);          if ($datatoken ne '') {
               &Apache::loncommon::load_tmp_file($r,$datatoken);
           }
     }      }
     my @records=&Apache::loncommon::upfile_record_sep();      my @records=&Apache::loncommon::upfile_record_sep();
     if ($env{'form.noFirstLine'}) { shift(@records); }      if ($env{'form.noFirstLine'}) { shift(@records); }
Line 2347  sub csvupload_fields { Line 2955  sub csvupload_fields {
     ['starttime','Start Time of slot'],      ['starttime','Start Time of slot'],
     ['endtime','End Time of slot'],      ['endtime','End Time of slot'],
     ['startreserve','Reservation Start Time'],      ['startreserve','Reservation Start Time'],
               ['endreserve','Reservation End Time'],
             ['reservationmsg','Message when reservation changed'],              ['reservationmsg','Message when reservation changed'],
     ['ip','IP or DNS restriction'],      ['ip','IP or DNS restriction'],
               ['iptied','Unique IP each student'],
     ['proctor','List of proctor ids'],      ['proctor','List of proctor ids'],
     ['description','Slot Description'],      ['description','Slot Description'],
     ['maxspace','Maximum number of reservations'],      ['maxspace','Maximum number of reservations'],
     ['symb','Resource Restriction'],      ['symb','Resource(s)/Map(s) Restriction'],
     ['uniqueperiod','Date range of slot exclusion'],      ['uniqueperiod','Date range of slot exclusion'],
     ['secret','Secret word proctor uses to validate'],      ['secret','Secret word proctor uses to validate'],
     ['allowedsections','Sections slot is restricted to'],      ['allowedsections','Sections slot is restricted to'],
Line 2362  sub csvupload_fields { Line 2972  sub csvupload_fields {
   
 sub csv_upload_assign {  sub csv_upload_assign {
     my ($r,$mgr)= @_;      my ($r,$mgr)= @_;
     &Apache::loncommon::load_tmp_file($r);      my $datatoken = &Apache::loncommon::valid_datatoken($env{'form.datatoken'});
       if ($datatoken ne '') {
           &Apache::loncommon::load_tmp_file($r,$datatoken);
       }
     my @slotdata = &Apache::loncommon::upfile_record_sep();      my @slotdata = &Apache::loncommon::upfile_record_sep();
     if ($env{'form.noFirstLine'}) { shift(@slotdata); }      if ($env{'form.noFirstLine'}) { shift(@slotdata); }
     my %fields=&Apache::grades::get_fields();      my %fields=&Apache::grades::get_fields();
Line 2420  sub csv_upload_assign { Line 3033  sub csv_upload_assign {
  }   }
   
  if ($entries{$fields{'startreserve'}}) {   if ($entries{$fields{'startreserve'}}) {
     $slot{'startreserve'}=              my $date = &UnixDate($entries{$fields{'startreserve'}},"%s");
  &UnixDate($entries{$fields{'startreserve'}},"%s");              if ($date eq '') {
                   push(@errors,"$name -- No reservation start time set for slot -- value provided had invalid format");
               } else {
                   $slot{'startreserve'} = $date;
               }
  }   }
  if (defined($slot{'startreserve'})   if (defined($slot{'startreserve'})
     && $slot{'startreserve'} > $slot{'starttime'}) {      && $slot{'startreserve'} > $slot{'starttime'}) {
Line 2429  sub csv_upload_assign { Line 3046  sub csv_upload_assign {
     next;      next;
  }   }
   
           if ($entries{$fields{'endreserve'}}) {
               my $date = &UnixDate($entries{$fields{'endreserve'}},"%s");
               if ($date eq '') {
                   push(@errors,"$name -- No reservation end time set for slot -- value provided had invalid format");
               } else {
                   $slot{'endreserve'} = $date;
               }
           }
           if (defined($slot{'endreserve'})
               && $slot{'endreserve'} > $slot{'starttime'}) {
               push(@errors,"$name not created -- Slot's reservation end time is after the slot's start time.");
               next;
           }
   
         if ($slot{'type'} eq 'schedulable_student') {          if ($slot{'type'} eq 'schedulable_student') {
             if ($entries{$fields{'reservationmsg'}}) {              if ($entries{$fields{'reservationmsg'}}) {
                  if (($entries{$fields{'reservationmsg'}} eq 'only_student') ||                   if (($entries{$fields{'reservationmsg'}} eq 'only_student') ||
Line 2449  sub csv_upload_assign { Line 3080  sub csv_upload_assign {
  $slot{$key}=$entries{$fields{$key}};   $slot{$key}=$entries{$fields{$key}};
     }      }
  }   }
           if ($entries{$fields{'iptied'}} =~ /^\s*(yes|1)\s*$/i) {
               $slot{'iptied'}='yes'; 
           } elsif ($entries{$fields{'iptied'}} =~ /^\s*answer\s*$/i) {
               $slot{'iptied'}='answer';
           }
           if ($entries{$fields{'allowedusers'}}) {
               $entries{$fields{'allowedusers'}} =~ s/^\s+//;
               $entries{$fields{'allowedusers'}} =~ s/\s+$//;
               my @allowedusers;
               foreach my $poss (split(/\s*,\s*/,$entries{$fields{'allowedusers'}})) {
                   my ($possuname,$possudom) = split(/:/,$poss);
                   if (($possuname =~ /^$match_username$/) && ($possudom =~ /^$match_domain$/)) {
                       unless (grep(/^\Q$poss\E$/,@allowedusers)) {
                           push(@allowedusers,$poss);
                       }
                   }
               }
               if (@allowedusers > 0) {
                   $slot{'allowedusers'} = join(',',@allowedusers);
               }
           }
           if ($entries{$fields{'allowedsections'}}) {
               $entries{$fields{'allowedsections'}} =~ s/^\s+//;
               $entries{$fields{'allowedsections'}} =~ s/\s+$//;
               my @allowedsections;
               foreach my $poss (split(/\s*,\s*/,$entries{$fields{'allowedsections'}})) {
                   if (($poss !~ /\W/) && ($poss ne 'none')) {
                       unless (grep(/^\Q$poss\E$/,@allowedsections)) {
                           push(@allowedsections,$poss);
                       }
                   }
               }
               if (@allowedsections > 0) {
                   $slot{'allowedsections'} = join(',',@allowedsections);
               }
           }
  if ($entries{$fields{'uniqueperiod'}}) {   if ($entries{$fields{'uniqueperiod'}}) {
     my ($start,$end)=split(',',$entries{$fields{'uniqueperiod'}});              my ($start,$end)= map { &UnixDate($_,"%s"); } split(',',$entries{$fields{'uniqueperiod'}});
     my @times=(&UnixDate($start,"%s"),              if (($start ne '') && ($end ne '')) {
        &UnixDate($end,"%s"));                  $slot{'uniqueperiod'}=[$start,$end];
     $slot{'uniqueperiod'}=\@times;              } else {
                   push(@errors,"$name -- Slot's unique period ignored -- one or both of the comma separated values for start and end had an invalid format");
               }
  }   }
  if (defined($slot{'uniqueperiod'})   if (ref($slot{'uniqueperiod'}) eq 'ARRAY' 
     && $slot{'uniqueperiod'}[0] > $slot{'uniqueperiod'}[1]) {      && $slot{'uniqueperiod'}[0] > $slot{'uniqueperiod'}[1]) {
     push(@errors,"$name not created -- Slot's unique period start time is later than the unique period's end time.");      push(@errors,"$name not created -- Slot's unique period start time is later than the unique period's end time.");
     next;      next;
Line 2467  sub csv_upload_assign { Line 3135  sub csv_upload_assign {
  $r->rflush();   $r->rflush();
  $countdone++;   $countdone++;
     }      }
       if ($countdone) {
           &Apache::lonnet::devalidate_slots_cache($cname,$cdom); 
       }
     $r->print('<p>'.&mt('Created [quant,_1,slot]',$countdone)."\n".'</p>');      $r->print('<p>'.&mt('Created [quant,_1,slot]',$countdone)."\n".'</p>');
     foreach my $error (@errors) {      foreach my $error (@errors) {
  $r->print('<p><span class="LC_warning">'.$error.'</span></p>'."\n");   $r->print('<p><span class="LC_warning">'.$error.'</span></p>'."\n");
Line 2518  sub handler { Line 3189  sub handler {
   
     my $vgr=&Apache::lonnet::allowed('vgr',$env{'request.course.id'});      my $vgr=&Apache::lonnet::allowed('vgr',$env{'request.course.id'});
     my $mgr=&Apache::lonnet::allowed('mgr',$env{'request.course.id'});      my $mgr=&Apache::lonnet::allowed('mgr',$env{'request.course.id'});
       my (%slots,$consumed_uniqueperiods);
     if ($env{'form.command'} eq 'showslots') {      if ($env{'form.command'} eq 'showslots') {
         if (($vgr ne 'F') && ($mgr ne 'F')) {          if (($vgr ne 'F') && ($mgr ne 'F')) {
             $env{'form.command'} = 'manageresv';               $env{'form.command'} = 'manageresv'; 
Line 2538  sub handler { Line 3210  sub handler {
         if (ref($brcrum) eq 'ARRAY') {          if (ref($brcrum) eq 'ARRAY') {
             push(@{$brcrum},{href=>"/adm/slotrequest?command=showresv",text=>$title});              push(@{$brcrum},{href=>"/adm/slotrequest?command=showresv",text=>$title});
         }          }
     } elsif ($env{'form.command'} eq 'manageresv') {      } elsif (($env{'form.requestattempt'}) || ($env{'form.command'} eq 'manageresv')) {  
         $title = 'Manage Reservations';          if ($env{'form.command'} eq 'manageresv') {
         $brcrum =[{href=>"/adm/slotrequest?command=manageresv",text=>$title}];              $title = 'Manage Reservations';
               $brcrum =[{href=>"/adm/slotrequest?command=manageresv",text=>$title}];
           }
           my ($cnum,$cdom)=&get_course();
           %slots = &Apache::lonnet::get_course_slots($cnum,$cdom);
           $consumed_uniqueperiods = &get_consumed_uniqueperiods(\%slots);
     } elsif ($vgr eq 'F') {      } elsif ($vgr eq 'F') {
         if ($env{'form.command'} =~ /^(slotlog|showslots|uploadstart|csvuploadmap|csvuploadassign|delete|release|remove_registration)$/) {          if ($env{'form.command'} =~ /^(slotlog|showslots|uploadstart|csvuploadmap|csvuploadassign|delete|release|remove_registration)$/) {
             $brcrum =[{href=>"/adm/slotrequest?command=showslots",              $brcrum =[{href=>"/adm/slotrequest?command=showslots",
Line 2560  sub handler { Line 3237  sub handler {
             if (ref($brcrum) eq 'ARRAY') {              if (ref($brcrum) eq 'ARRAY') {
                 push(@{$brcrum},{href=>"/adm/slotrequest?command=$env{'form.command'}",text=>$crumb_titles{$env{'form.command'}}});                  push(@{$brcrum},{href=>"/adm/slotrequest?command=$env{'form.command'}",text=>$crumb_titles{$env{'form.command'}}});
             }              }
               
         }          }
       } else {
           $brcrum =[];
       }
       my ($symb,$js,$available,$allavailable,$got_slots);
       $available = [];
       if ($env{'form.requestattempt'}) {
           $symb=&unescape($env{'form.symb'});
           @{$got_slots}=&check_for_reservation($symb,'allslots');
       }
       if (($env{'form.requestattempt'}) || ($env{'form.command'} eq 'manageresv')) {
           $js = &reservation_js(\%slots,$consumed_uniqueperiods,$available,$got_slots,$symb);
     }      }
     &start_page($r,$title,$brcrum);      &start_page($r,$title,$brcrum,$js);
   
     if ($env{'form.command'} eq 'manageresv') {      if ($env{'form.command'} eq 'manageresv') {
           $allavailable = $available;
           undef($available);
           undef($got_slots);
         my $crstype = &Apache::loncommon::course_type();          my $crstype = &Apache::loncommon::course_type();
         &manage_reservations($r,$crstype);          &manage_reservations($r,$crstype,\%slots,$consumed_uniqueperiods,$allavailable);
     } elsif ($env{'form.command'} eq 'showresv') {      } elsif ($env{'form.command'} eq 'showresv') {
         &show_reservations($r,$env{'form.uname'},$env{'form.udom'});          &show_reservations($r,$env{'form.uname'},$env{'form.udom'});
     } elsif ($env{'form.command'} eq 'showslots' && $vgr eq 'F') {      } elsif ($env{'form.command'} eq 'showslots' && $vgr eq 'F') {
Line 2597  sub handler { Line 3287  sub handler {
     }      }
     &csv_upload_map($r);      &csv_upload_map($r);
  }   }
     } elsif ($env{'form.command'} eq 'slotlog' && $mgr eq 'F') {      } elsif (($env{'form.command'} eq 'slotlog') && ($vgr eq 'F')) {
         &show_reservations_log($r);          &show_reservations_log($r);
     } else {      } else {
  my $symb=&unescape($env{'form.symb'});   my $symb=&unescape($env{'form.symb'});
Line 2619  sub handler { Line 3309  sub handler {
  my ($status) = &Apache::lonhomework::check_slot_access('0',$type);   my ($status) = &Apache::lonhomework::check_slot_access('0',$type);
  if ($status eq 'CAN_ANSWER' ||   if ($status eq 'CAN_ANSWER' ||
     $status eq 'NEEDS_CHECKIN' ||      $status eq 'NEEDS_CHECKIN' ||
     $status eq 'WAITING_FOR_GRADE') {      $status eq 'WAITING_FOR_GRADE' ||
               $status eq 'NEED_DIFFERENT_IP') {
     &fail($r,'not_allowed');      &fail($r,'not_allowed');
     return OK;      return OK;
  }   }
  if ($env{'form.requestattempt'}) {   if ($env{'form.requestattempt'}) {
     &show_choices($r,$symb);              $r->print('<div class="LC_left_float">'); 
       $r->print(&show_choices($symb,undef,undef,undef,\%slots,$consumed_uniqueperiods,$available,$got_slots));
               $r->print('</div><div style="padding:0;clear:both;margin:0;border:0"></div>');
  } elsif ($env{'form.command'} eq 'release') {   } elsif ($env{'form.command'} eq 'release') {
     &release_slot($r,$symb);      &release_slot($r,$symb);
  } elsif ($env{'form.command'} eq 'get') {   } elsif ($env{'form.command'} eq 'get') {

Removed from v.1.110  
changed lines
  Added in v.1.138


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.