Annotation of loncom/interface/slotrequest.pm, revision 1.51

1.1       albertel    1: # The LearningOnline Network with CAPA
                      2: # Handler for requesting to have slots added to a students record
                      3: #
1.51    ! albertel    4: # $Id: slotrequest.pm,v 1.50 2006/03/07 21:37:29 albertel Exp $
1.1       albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
                     28: ###
                     29: 
                     30: package Apache::slotrequest;
                     31: 
                     32: use strict;
                     33: use Apache::Constants qw(:common :http :methods);
                     34: use Apache::loncommon();
                     35: use Apache::lonlocal;
                     36: use Apache::lonnet;
1.48      albertel   37: use Apache::lonnavmaps();
1.27      albertel   38: use Date::Manip;
1.1       albertel   39: 
                     40: sub fail {
                     41:     my ($r,$code)=@_;
1.2       albertel   42:     if ($code eq 'not_valid') {
1.8       albertel   43: 	$r->print('<p>'.&mt('Unable to understand what resource you wanted to sign up for.').'</p>');
1.2       albertel   44: 
1.8       albertel   45:     } elsif ($code eq 'not_allowed') {
                     46: 	$r->print('<p>'.&mt('Not allowed to sign up or change reservations at this time.').'</p>');
                     47:     } else {
                     48: 	$r->print('<p>'.&mt('Failed.').'</p>');
1.2       albertel   49:     }
1.8       albertel   50:     
1.42      albertel   51:     &return_link($r);
1.1       albertel   52:     &end_page($r);
                     53: }
                     54: 
                     55: sub start_page {
1.28      albertel   56:     my ($r,$title)=@_;
1.1       albertel   57:     my $html=&Apache::lonxml::xmlbegin();
1.28      albertel   58:     $r->print($html.'<head><title>'.&mt($title).'</title></head>');
                     59:     $r->print(&Apache::loncommon::bodytag($title));
1.1       albertel   60: }
                     61: 
                     62: sub end_page {
                     63:     my ($r)=@_;
                     64:     $r->print(&Apache::loncommon::endbodytag().'</html>');
                     65: }
                     66: 
1.2       albertel   67: =pod
                     68: 
                     69:  slot_reservations db
                     70:    - keys are 
                     71:     - slotname\0id -> value is an hashref of
                     72:                          name -> user@domain of holder
                     73:                          timestamp -> timestamp of reservation
                     74:                          symb -> symb of resource that it is reserved for
                     75: 
                     76: =cut
                     77: 
                     78: sub get_course {
                     79:     (undef,my $courseid)=&Apache::lonxml::whichuser();
                     80:     my $cdom=$env{'course.'.$courseid.'.domain'};
                     81:     my $cnum=$env{'course.'.$courseid.'.num'};
                     82:     return ($cnum,$cdom);
                     83: }
                     84: 
                     85: sub get_reservation_ids {
                     86:     my ($slot_name)=@_;
                     87:     
                     88:     my ($cnum,$cdom)=&get_course();
                     89: 
                     90:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                     91: 				       "^$slot_name\0");
1.40      albertel   92:     if (&network_error(%consumed)) { 
                     93: 	return 'error: Unable to determine current status';
                     94:     }
1.2       albertel   95:     my ($tmp)=%consumed;
                     96:     if ($tmp=~/^error: 2 / ) {
                     97: 	return 0;
                     98:     }
                     99:     return keys(%consumed);
                    100: }
                    101: 
                    102: sub space_available {
                    103:     my ($slot_name,$slot)=@_;
                    104:     my $max=$slot->{'maxspace'};
                    105: 
                    106:     if (!defined($max)) { return 1; }
                    107: 
                    108:     my $consumed=scalar(&get_reservation_ids($slot_name));
                    109:     if ($consumed < $max) {
                    110: 	return 1
                    111:     }
                    112:     return 0;
                    113: }
1.3       albertel  114: 
1.4       albertel  115: sub check_for_reservation {
1.43      albertel  116:     my ($symb,$mode)=@_;
1.4       albertel  117:     my $student = &Apache::lonnet::EXT("resource.0.availablestudent", $symb,
                    118: 				       $env{'user.domain'}, $env{'user.name'});
                    119: 
                    120:     my $course = &Apache::lonnet::EXT("resource.0.available", $symb,
                    121: 				    $env{'user.domain'}, $env{'user.name'});
                    122:     my @slots = (split(/:/,$student), split(/:/, $course));
                    123: 
                    124:     &Apache::lonxml::debug(" slot list is ".join(':',@slots));
                    125: 
                    126:     my ($cnum,$cdom)=&get_course();
                    127:     my %slots=&Apache::lonnet::get('slots', [@slots], $cdom, $cnum);
                    128: 
1.41      albertel  129:     if (&network_error($student) || &network_error($course)  ||
                    130: 	&network_error(%slots)) {
                    131: 	return 'error: Unable to determine current status';
                    132:     }    
1.43      albertel  133:     my @got;
                    134:     foreach my $slot_name (sort {
                    135: 	if (ref($slots{$a}) && ref($slots{$b})) {
                    136: 	    return $slots{$a}{'starttime'} <=> $slots{$b}{'starttime'}
                    137: 	}
                    138: 	if (ref($slots{$a})) { return -1;}
                    139: 	if (ref($slots{$b})) { return 1;}
                    140: 	return 0;
                    141:     } @slots) {
1.4       albertel  142: 	next if (!defined($slots{$slot_name}) ||
                    143: 		 !ref($slots{$slot_name}));
                    144: 	&Apache::lonxml::debug(time." $slot_name ".
                    145: 			       $slots{$slot_name}->{'starttime'}." -- ".
                    146: 			       $slots{$slot_name}->{'startreserve'});
1.7       albertel  147: 	if ($slots{$slot_name}->{'endtime'} > time &&
1.4       albertel  148: 	    $slots{$slot_name}->{'startreserve'} < time) {
1.7       albertel  149: 	    # between start of reservation times and end of slot
1.43      albertel  150: 	    if ($mode eq 'allslots') {
                    151: 		push(@got,$slot_name);
                    152: 	    } else {
                    153: 		return($slot_name, $slots{$slot_name});
                    154: 	    }
1.4       albertel  155: 	}
                    156:     }
1.43      albertel  157:     if ($mode eq 'allslots' && @got) {
                    158: 	return @got;
                    159:     }
1.4       albertel  160:     return (undef,undef);
                    161: }
                    162: 
1.48      albertel  163: sub get_consumed_uniqueperiods {
                    164:     my ($slots) = @_;
                    165:     my $navmap=Apache::lonnavmaps::navmap->new;
                    166:     my @problems = $navmap->retrieveResources(undef,
                    167: 					      sub { $_[0]->is_problem() },1,0);
                    168:     my %used_slots;
                    169:     foreach my $problem (@problems) {
                    170: 	my $symb = $problem->symb();
                    171: 	my $student = &Apache::lonnet::EXT("resource.0.availablestudent",
                    172: 					   $symb, $env{'user.domain'},
                    173: 					   $env{'user.name'});
                    174: 	my $course =  &Apache::lonnet::EXT("resource.0.available",
                    175: 					   $symb, $env{'user.domain'},
                    176: 					   $env{'user.name'});
                    177: 	if (&network_error($student) || &network_error($course)) {
                    178: 	    return 'error: Unable to determine current status';
                    179: 	}
                    180: 	foreach my $slot (split(/:/,$student), split(/:/, $course)) {
                    181: 	    $used_slots{$slot}=1;
                    182: 	}
                    183:     }
1.43      albertel  184: 
                    185:     if (!ref($slots)) {
1.48      albertel  186: 	my ($cnum,$cdom)=&get_course();
                    187: 	my %slots=&Apache::lonnet::get('slots', [keys(%used_slots)], $cdom, $cnum);
                    188: 	if (&network_error(%slots)) {
                    189: 	    return 'error: Unable to determine current status';
                    190: 	}
1.43      albertel  191: 	$slots = \%slots;
                    192:     }
1.41      albertel  193: 
1.48      albertel  194:     my %consumed_uniqueperiods;
                    195:     foreach my $slot_name (keys(%used_slots)) {
1.43      albertel  196: 	next if (!defined($slots->{$slot_name}) ||
                    197: 		 !ref($slots->{$slot_name}));
1.48      albertel  198: 	
1.43      albertel  199:         next if (!defined($slots->{$slot_name}{'uniqueperiod'}) ||
                    200: 		 !ref($slots->{$slot_name}{'uniqueperiod'}));
1.48      albertel  201: 	$consumed_uniqueperiods{$slot_name} = 
                    202: 	    $slots->{$slot_name}{'uniqueperiod'};
                    203:     }
                    204:     return \%consumed_uniqueperiods;
                    205: }
                    206: 
                    207: sub check_for_conflict {
                    208:     my ($symb,$new_slot_name,$new_slot,$slots,$consumed_uniqueperiods)=@_;
                    209: 
                    210:     if (!defined($new_slot->{'uniqueperiod'})) { return undef; }
                    211: 
                    212:     if (!ref($consumed_uniqueperiods)) {
                    213: 	$consumed_uniqueperiods = &get_consumed_uniqueperiods($slots);
                    214: 	if (&network_error(%$consumed_uniqueperiods)) {
                    215: 	    return 'error: Unable to determine current status';
                    216: 	}
                    217:     }
                    218:     
                    219:     my ($new_uniq_start,$new_uniq_end) = @{$new_slot->{'uniqueperiod'}};
                    220:     foreach my $slot_name (keys(%$consumed_uniqueperiods)) {
                    221: 	my ($start,$end)=@{$consumed_uniqueperiods->{$slot_name}};
1.43      albertel  222: 	if (!
                    223: 	    ($start < $new_uniq_start &&  $end < $new_uniq_start) ||
                    224: 	    ($start > $new_uniq_end   &&  $end > $new_uniq_end  )) {
1.5       albertel  225: 	    return $slot_name;
                    226: 	}
                    227:     }
                    228:     return undef;
                    229: 
                    230: }
                    231: 
1.40      albertel  232: sub network_error {
                    233:     my ($result) = @_;
                    234:     if ($result =~ /^(con_lost|no_such_host|error: [^2])/) {
                    235: 	return 1;
                    236:     }
                    237:     return 0;
                    238: }
                    239: 
1.2       albertel  240: sub make_reservation {
                    241:     my ($slot_name,$slot,$symb)=@_;
1.3       albertel  242: 
                    243:     my ($cnum,$cdom)=&get_course();
                    244: 
                    245:     my $value=&Apache::lonnet::EXT("resource.0.availablestudent",$symb,
                    246: 				   $env{'user.domain'},$env{'user.name'});
                    247:     &Apache::lonxml::debug("value is  $value<br />");
1.40      albertel  248:     if (&network_error($value)) { 
                    249: 	return 'error: Unable to determine current status';
                    250:     }
                    251: 
1.3       albertel  252:     foreach my $other_slot (split(/:/, $value)) {
                    253: 	if ($other_slot eq $slot_name) {
                    254: 	    my %consumed=&Apache::lonnet::dump('slot_reservations', $cdom,
                    255: 					       $cnum, "^$slot_name\0");   
1.40      albertel  256: 	    if (&network_error($value)) { 
                    257: 		return 'error: Unable to determine current status';
                    258: 	    }
1.3       albertel  259: 	    my $me=$env{'user.name'}.'@'.$env{'user.domain'};
                    260: 	    foreach my $key (keys(%consumed)) {
                    261: 		if ($consumed{$key}->{'name'} eq $me) {
                    262: 		    my $num=(split('\0',$key))[1];
                    263: 		    return -$num;
                    264: 		}
                    265: 	    }
                    266: 	}
                    267:     }
                    268: 
1.2       albertel  269:     my $max=$slot->{'maxspace'};
1.3       albertel  270:     if (!defined($max)) { $max=99999; }
1.2       albertel  271: 
                    272:     my (@ids)=&get_reservation_ids($slot_name);
1.40      albertel  273:     if (&network_error(@ids)) { 
                    274: 	return 'error: Unable to determine current status';
                    275:     }
1.2       albertel  276:     my $last=0;
                    277:     foreach my $id (@ids) {
                    278: 	my $num=(split('\0',$id))[1];
                    279: 	if ($num > $last) { $last=$num; }
                    280:     }
                    281:     
                    282:     my $wanted=$last+1;
1.3       albertel  283:     &Apache::lonxml::debug("wanted $wanted<br />");
1.7       albertel  284:     if (scalar(@ids) >= $max) {
1.2       albertel  285: 	# full up
1.7       albertel  286: 	return undef;
1.2       albertel  287:     }
                    288:     
                    289:     my %reservation=('name'      => $env{'user.name'}.'@'.$env{'user.domain'},
                    290: 		     'timestamp' => time,
                    291: 		     'symb'      => $symb);
                    292: 
                    293:     my $success=&Apache::lonnet::newput('slot_reservations',
                    294: 					{"$slot_name\0$wanted" =>
                    295: 					     \%reservation},
1.3       albertel  296: 					$cdom, $cnum);
                    297: 
1.2       albertel  298:     if ($success eq 'ok') {
1.3       albertel  299: 	my $new_value=$slot_name;
                    300: 	if ($value) {
                    301: 	    $new_value=$value.':'.$new_value;
                    302: 	}
                    303: 	my $result=&Apache::lonparmset::storeparm_by_symb($symb,
                    304: 						      '0_availablestudent',
                    305: 						       1, $new_value, 'string',
                    306: 						       $env{'user.name'},
                    307: 					               $env{'user.domain'});
                    308: 	&Apache::lonxml::debug("hrrm $result");
1.2       albertel  309: 	return $wanted;
                    310:     }
1.3       albertel  311: 
1.2       albertel  312:     # someone else got it
1.3       albertel  313:     return undef;
                    314: }
                    315: 
1.33      albertel  316: sub remove_registration {
                    317:     my ($r) = @_;
                    318:     my $name = &Apache::loncommon::plainname($env{'form.uname'},
                    319: 					     $env{'form.udom'});
                    320: 
                    321:     my $title = &Apache::lonnet::gettitle($env{'form.symb'});
                    322: 
                    323:     my $hidden_input;
                    324:     foreach my $parm ('uname','udom','slotname','entry','symb') {
                    325: 	$hidden_input .=
                    326: 	    '<input type="hidden" name="'.$parm.'" value="'
                    327: 	    .&HTML::Entities::encode($env{'form.'.$parm},'"<>&\'').'" />'."\n";
                    328:     }
                    329:     $r->print(<<"END_CONFIRM");
                    330: <p> Remove $name from slot $env{'form.slotname'} for $title</p>
                    331: <form action="/adm/slotrequest" method="POST">
                    332:     <input type="hidden" name="command" value="release" />
                    333:     $hidden_input
                    334:     <input type="submit" name="Yes" value="yes" />
                    335: </form>
                    336: <form action="/adm/slotrequest" method="POST">
                    337:     <input type="hidden" name="command" value="showslots" />
                    338:     <input type="submit" name="No" value="no" />
                    339: </form>
                    340: END_CONFIRM
                    341: 
                    342: }
                    343: 
1.5       albertel  344: sub release_slot {
1.33      albertel  345:     my ($r,$symb,$slot_name,$inhibit_return_link,$mgr)=@_;
1.6       albertel  346: 
                    347:     if ($slot_name eq '') { $slot_name=$env{'form.slotname'}; }
                    348:     my ($cnum,$cdom)=&get_course();
                    349: 
1.33      albertel  350:     my ($uname,$udom) = ($env{'user.name'}, $env{'user.domain'});
                    351:     if ($mgr eq 'F' 
                    352: 	&& defined($env{'form.uname'}) && defined($env{'form.udom'})) {
                    353: 	($uname,$udom) = ($env{'form.uname'}, $env{'form.udom'});
                    354:     }
                    355: 
                    356:     if ($mgr eq 'F' 
                    357: 	&& defined($env{'form.symb'})) {
                    358: 	$symb = $env{'form.symb'};
                    359:     }
1.39      albertel  360:     my %slot=&Apache::lonnet::get_slot($slot_name);
                    361:     my $description=&get_description($env{'form.slotname'},\%slot);
1.33      albertel  362: 
1.39      albertel  363:     if ($mgr ne 'F') {
1.43      albertel  364: 	if ($slot{'starttime'} < time) {
                    365: 	    $r->print("<p>Not allowed to release Reservation: $description, as it has already ended.  </p>");
1.42      albertel  366: 	    &return_link($r);
1.39      albertel  367: 	    return 0;
                    368: 	}
                    369:     }
1.5       albertel  370:     # get parameter string, check for existance, rebuild string with the slot
1.6       albertel  371:     my @slots = split(/:/,&Apache::lonnet::EXT("resource.0.availablestudent",
1.33      albertel  372: 					       $symb,$udom,$uname));
                    373: 
1.6       albertel  374:     my @new_slots;
                    375:     foreach my $exist_slot (@slots) {
                    376: 	if ($exist_slot eq $slot_name) { next; }
                    377: 	push(@new_slots,$exist_slot);
                    378:     }
                    379:     my $new_param = join(':',@new_slots);
1.5       albertel  380: 
                    381:     # get slot reservations, check if user has one, if so remove reservation
1.6       albertel  382:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                    383: 				       "^$slot_name\0");
                    384:     foreach my $entry (keys(%consumed)) {
1.33      albertel  385: 	if ( $consumed{$entry}->{'name'} eq ($uname.'@'.$udom) ) {
1.6       albertel  386: 	    &Apache::lonnet::del('slot_reservations',[$entry],
                    387: 				 $cdom,$cnum);
                    388: 	}
                    389:     }
1.33      albertel  390: 
1.5       albertel  391:     # store new parameter string
1.6       albertel  392:     my $result=&Apache::lonparmset::storeparm_by_symb($symb,
                    393: 						      '0_availablestudent',
                    394: 						      1, $new_param, 'string',
1.33      albertel  395: 						      $uname,$udom);
1.6       albertel  396:     $r->print("<p>Released Reservation: $description</p>");
1.33      albertel  397:     if ($mgr eq 'F') {
                    398: 	$r->print('<p><a href="/adm/slotrequest?command=showslots">'.
                    399: 		  &mt('Return to slot list').'</a></p>');
                    400:     }
1.42      albertel  401:     if (!$inhibit_return_link) { &return_link($r);  }
1.6       albertel  402:     return 1;
1.5       albertel  403: }
                    404: 
1.34      albertel  405: sub delete_slot {
                    406:     my ($r)=@_;
                    407: 
                    408:     my $slot_name = $env{'form.slotname'};
                    409:     my %slot=&Apache::lonnet::get_slot($slot_name);
                    410: 
                    411:     my ($cnum,$cdom)=&get_course();
                    412:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                    413: 				       "^$slot_name\0");
1.38      albertel  414:     my ($tmp) = %consumed;
                    415:     if ($tmp =~ /error: 2/) { undef(%consumed); }
1.34      albertel  416: 
                    417:     if (%slot && !%consumed) {
                    418: 	$slot{'type'} = 'deleted';
                    419: 	my $ret = &Apache::lonnet::cput('slots', {$slot_name => \%slot},
                    420: 					$cdom, $cnum);
                    421: 	if ($ret eq 'ok') {
                    422: 	    $r->print("<p>Slot <tt>$slot_name</tt> marked as deleted.</p>");
                    423: 	} else {
                    424: 	    $r->print("<p> An error ($ret) occurse when attempting to delete Slot <tt>$slot_name</tt>.</p>");
                    425: 	}
                    426:     } else {
                    427: 	if (%consumed) {
                    428: 	    $r->print("<p>Slot <tt>$slot_name</tt> has active reservations.</p>");
                    429: 	} else {
                    430: 	    $r->print("<p>Slot <tt>$slot_name</tt> does not exist.</p>");
                    431: 	}
                    432:     }
                    433:     $r->print('<p><a href="/adm/slotrequest?command=showslots">'.
                    434: 	      &mt('Return to slot list').'</a></p>');
1.42      albertel  435:     &return_link($r);
1.34      albertel  436: }
                    437: 
1.40      albertel  438: sub return_link {
                    439:     my ($r) = @_;
                    440:     $r->print('<p><a href="/adm/flip?postdata=return:">'.
                    441: 	      &mt('Return to last resource').'</a></p>');
                    442: }
                    443: 
1.3       albertel  444: sub get_slot {
                    445:     my ($r,$symb)=@_;
                    446: 
1.43      albertel  447:     my %slot=&Apache::lonnet::get_slot($env{'form.slotname'});
                    448:     my $slot_name=&check_for_conflict($symb,$env{'form.slotname'},\%slot);
1.40      albertel  449: 
                    450:     if ($slot_name =~ /^error: (.*)/) {
                    451: 	$r->print("<p>An error occured while attempting to make a reservation. ($1)</p>");
                    452: 	&return_link($r);
                    453: 	return;
                    454:     }
1.5       albertel  455:     if ($slot_name) {
                    456: 	my %slot=&Apache::lonnet::get_slot($slot_name);
1.6       albertel  457: 	my $description1=&get_description($slot_name,\%slot);
                    458: 	%slot=&Apache::lonnet::get_slot($env{'form.slotname'});
                    459: 	my $description2=&get_description($env{'form.slotname'},\%slot);
                    460: 	$r->print("<p>Already have a reservation: $description1</p>");
1.7       albertel  461: 	if ($slot_name ne $env{'form.slotname'}) {
                    462: 	    $r->print(<<STUFF);
1.6       albertel  463: <form method="POST" action="/adm/slotrequest">
                    464:    <input type="hidden" name="symb" value="$env{'form.symb'}" />
                    465:    <input type="hidden" name="slotname" value="$env{'form.slotname'}" />
                    466:    <input type="hidden" name="releaseslot" value="$slot_name" />
                    467:    <input type="hidden" name="command" value="change" />
                    468: STUFF
1.7       albertel  469:             $r->print("<p>You can either ");
                    470: 	    $r->print(<<STUFF);
1.6       albertel  471:    <input type="submit" name="change" value="Change" />
                    472: STUFF
1.7       albertel  473: 	    $r->print(' your reservation from <b>'.$description1.'</b> to <b>'.
                    474: 		      $description2.
1.40      albertel  475: 		      '</b> <br />or </p>');
                    476: 	    &return_link($r);
1.7       albertel  477: 	    $r->print(<<STUFF);
1.6       albertel  478: </form>
                    479: STUFF
1.7       albertel  480:         } else {
1.40      albertel  481: 	    &return_link($r);
1.7       albertel  482: 	}
1.5       albertel  483: 	return;
                    484:     }
1.45      albertel  485: 
1.3       albertel  486:     my $reserved=&make_reservation($env{'form.slotname'},
                    487: 				   \%slot,$symb);
                    488:     my $description=&get_description($env{'form.slotname'},\%slot);
1.7       albertel  489:     if (defined($reserved)) {
1.40      albertel  490: 	if ($slot_name =~ /^error: (.*)/) {
                    491: 	    $r->print("<p>An error occured while attempting to make a reservation. ($1)</p>");
                    492: 	} elsif ($reserved > -1) {
1.7       albertel  493: 	    $r->print("<p>Success: $description</p>");
                    494: 	} elsif ($reserved < 0) {
                    495: 	    $r->print("<p>Already reserved: $description</p>");
                    496: 	}
1.40      albertel  497: 	&return_link($r);
                    498: 	return;
1.3       albertel  499:     }
                    500: 
1.7       albertel  501:     my %lt=('request'=>"Availibility list",
1.3       albertel  502: 	    'try'    =>'Try again');
                    503:     %lt=&Apache::lonlocal::texthash(%lt);
                    504: 
                    505:     $r->print(<<STUFF);
                    506: <p> <font color="red">Failed</font> to reserve a spot for $description. </p>
                    507: <p>
                    508: <form method="POST" action="/adm/slotrequest">
                    509:    <input type="submit" name="Try Again" value="$lt{'try'}" />
                    510:    <input type="hidden" name="symb" value="$env{'form.symb'}" />
                    511:    <input type="hidden" name="slotname" value="$env{'form.slotname'}" />
                    512:    <input type="hidden" name="command" value="get" />
                    513: </form>
                    514: ?
                    515: </p>
                    516: <p>
                    517: or
                    518: <form method="POST" action="/adm/slotrequest">
                    519:     <input type="hidden" name="symb" value="$env{'form.symb'}" />
                    520:     <input type="submit" name="requestattempt" value="$lt{'request'}" />
                    521: </form>
                    522: </p>
                    523: or
                    524: STUFF
1.42      albertel  525: 
                    526:     &return_link($r);
1.3       albertel  527:     return;
                    528: }
                    529: 
                    530: sub allowed_slot {
1.48      albertel  531:     my ($slot_name,$slot,$symb,$slots,$consumed_uniqueperiods)=@_;
1.49      albertel  532: 
1.3       albertel  533:     #already started
                    534:     if ($slot->{'starttime'} < time) {
1.5       albertel  535: 	# all open slot to be schedulable
                    536: 	#return 0;
1.3       albertel  537:     }
1.5       albertel  538:     &Apache::lonxml::debug("$slot_name starttime good");
1.49      albertel  539: 
1.3       albertel  540:     #already ended
                    541:     if ($slot->{'endtime'} < time) {
                    542: 	return 0;
                    543:     }
1.5       albertel  544:     &Apache::lonxml::debug("$slot_name endtime good");
1.49      albertel  545: 
1.3       albertel  546:     # not allowed to pick this one
                    547:     if (defined($slot->{'type'})
                    548: 	&& $slot->{'type'} ne 'schedulable_student') {
                    549: 	return 0;
                    550:     }
1.5       albertel  551:     &Apache::lonxml::debug("$slot_name type good");
1.49      albertel  552: 
1.50      albertel  553:     my $userallowed=0;
1.49      albertel  554:     # its for a different set of users
1.50      albertel  555:     if (defined($slot->{'allowedsections'})) {
                    556: 	if (!defined($env{'request.role.sec'})
                    557: 	    && grep(/^No section assigned$/,
                    558: 		    split(',',$slot->{'allowedsections'}))) {
                    559: 	    $userallowed=1;
                    560: 	}
                    561: 	if (defined($env{'request.role.sec'})
                    562: 	    && grep(/^\Q$env{'request.role.sec'}\E$/,
                    563: 		    split(',',$slot->{'allowedsections'}))) {
                    564: 	    $userallowed=1;
                    565: 	}
1.49      albertel  566:     }
1.50      albertel  567:     &Apache::lonxml::debug("$slot_name sections is $userallowed");
1.49      albertel  568: 
                    569:     # its for a different set of users
1.50      albertel  570:     if (defined($slot->{'allowedusers'})
                    571: 	&& grep(/^\Q$env{'user.name'}:$env{'user.domain'}\E$/,
                    572: 		split(',',$slot->{'allowedusers'}))) {
                    573: 	$userallowed=1;
1.49      albertel  574:     }
1.51    ! albertel  575: 
        !           576:     if (!defined($slot->{'allowedusers'})
        !           577: 	&& !defined($slot->{'allowedsections'})) {
        !           578: 	$userallowed=1;
        !           579:     }
        !           580: 
1.50      albertel  581:     &Apache::lonxml::debug("$slot_name user is $userallowed");
                    582:     return 0 if (!$userallowed);
1.49      albertel  583: 
1.3       albertel  584:     # not allowed for this resource
                    585:     if (defined($slot->{'symb'})
                    586: 	&& $slot->{'symb'} ne $symb) {
                    587: 	return 0;
                    588:     }
1.50      albertel  589: 
1.48      albertel  590:     my $conflict = &check_for_conflict($symb,$slot_name,$slot,$slots,
                    591: 				       $consumed_uniqueperiods);
1.44      albertel  592:     if ($conflict) {
                    593: 	if ($slots->{$conflict}{'starttime'} < time) {
                    594: 	    return 0;
                    595: 	}
                    596:     }
1.5       albertel  597:     &Apache::lonxml::debug("$slot_name symb good");
1.3       albertel  598:     return 1;
1.2       albertel  599: }
                    600: 
1.3       albertel  601: sub get_description {
                    602:     my ($slot_name,$slot)=@_;
                    603:     my $description=$slot->{'description'};
                    604:     if (!defined($description)) {
1.4       albertel  605: 	$description=&mt('[_1] From [_2] to [_3]',$slot_name,
1.3       albertel  606: 			 &Apache::lonlocal::locallocaltime($slot->{'starttime'}),
                    607: 			 &Apache::lonlocal::locallocaltime($slot->{'endtime'}));
                    608:     }
                    609:     return $description;
                    610: }
1.2       albertel  611: 
                    612: sub show_choices {
                    613:     my ($r,$symb)=@_;
                    614: 
                    615:     my ($cnum,$cdom)=&get_course();
                    616:     my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum);
1.48      albertel  617:     my $consumed_uniqueperiods = &get_consumed_uniqueperiods(\%slots);
1.3       albertel  618:     my $available;
1.2       albertel  619:     $r->print('<table border="1">');
1.5       albertel  620:     &Apache::lonxml::debug("Checking Slots");
1.43      albertel  621:     my @got_slots=&check_for_reservation($symb,'allslots');
1.2       albertel  622:     foreach my $slot (sort 
                    623: 		      { return $slots{$a}->{'starttime'} <=> $slots{$b}->{'starttime'} }
                    624: 		      (keys(%slots)))  {
1.5       albertel  625: 
                    626: 	&Apache::lonxml::debug("Checking Slot $slot");
1.48      albertel  627: 	next if (!&allowed_slot($slot,$slots{$slot},undef,\%slots,
                    628: 				$consumed_uniqueperiods));
1.3       albertel  629: 
                    630: 	$available++;
                    631: 
                    632: 	my $description=&get_description($slot,$slots{$slot});
1.2       albertel  633: 
                    634: 	my $form=&mt('Unavailable');
1.43      albertel  635: 	if ((grep(/^\Q$slot\E$/,@got_slots)) ||
1.7       albertel  636: 	    &space_available($slot,$slots{$slot},$symb)) {
1.5       albertel  637: 	    my $text=&mt('Select');
                    638: 	    my $command='get';
1.43      albertel  639: 	    if (grep(/^\Q$slot\E$/,@got_slots)) {
1.5       albertel  640: 		$text=&mt('Free Reservation');
                    641: 		$command='release';
1.43      albertel  642: 	    } else {
                    643: 		my $conflict = &check_for_conflict($symb,$slot,$slots{$slot},
1.48      albertel  644: 						   \%slots,
                    645: 						   $consumed_uniqueperiods);
1.43      albertel  646: 		if ($conflict) {
                    647: 		    $text=&mt('Change Reservation');
                    648: 		    $command='get';
                    649: 		}
1.5       albertel  650: 	    }
1.3       albertel  651: 	    my $escsymb=&Apache::lonnet::escape($symb);
1.2       albertel  652: 	    $form=<<STUFF;
1.3       albertel  653:    <form method="POST" action="/adm/slotrequest">
1.5       albertel  654:      <input type="submit" name="Select" value="$text" />
1.3       albertel  655:      <input type="hidden" name="symb" value="$escsymb" />
                    656:      <input type="hidden" name="slotname" value="$slot" />
1.5       albertel  657:      <input type="hidden" name="command" value="$command" />
1.2       albertel  658:    </form>
                    659: STUFF
                    660: 	}
                    661: 	$r->print(<<STUFF);
                    662: <tr>
                    663:  <td>$form</td>
                    664:  <td>$description</td>
                    665: </tr>
                    666: STUFF
                    667:     }
1.3       albertel  668: 
                    669:     if (!$available) {
1.5       albertel  670: 	$r->print('<tr><td>No available times. <a href="/adm/flip?postdata=return:">'.
1.3       albertel  671: 		  &mt('Return to last resource').'</a></td></tr>');
                    672:     }
1.2       albertel  673:     $r->print('</table>');
                    674: }
                    675: 
1.30      albertel  676: sub to_show {
1.35      albertel  677:     my ($slot,$when,$deleted) = @_;
1.30      albertel  678:     my $time=time;
                    679:     my $week=60*60*24*7;
1.35      albertel  680:     if ($deleted eq 'hide' && $slot->{'type'} eq 'deleted') {
                    681: 	return 0;
                    682:     }
                    683:     if ($when eq 'any') {
                    684: 	return 1;
                    685:     } elsif ($when eq 'now') {
1.30      albertel  686: 	if ($time > $slot->{'starttime'} &&
                    687: 	    $time < $slot->{'endtime'}) {
                    688: 	    return 1;
                    689: 	}
                    690: 	return 0;
                    691:     } elsif ($when eq 'nextweek') {
                    692: 	if ( ($time        < $slot->{'starttime'} &&
                    693: 	      ($time+$week) > $slot->{'starttime'})
                    694: 	     ||
                    695: 	     ($time        < $slot->{'endtime'} &&
                    696: 	      ($time+$week) > $slot->{'endtime'}) ) {
                    697: 	    return 1;
                    698: 	}
                    699: 	return 0;
                    700:     } elsif ($when eq 'lastweek') {
                    701: 	if ( ($time        > $slot->{'starttime'} &&
                    702: 	      ($time-$week) < $slot->{'starttime'})
                    703: 	     ||
                    704: 	     ($time        > $slot->{'endtime'} &&
                    705: 	      ($time-$week) < $slot->{'endtime'}) ) {
                    706: 	    return 1;
                    707: 	}
                    708: 	return 0;
                    709:     } elsif ($when eq 'willopen') {
                    710: 	if ($time < $slot->{'starttime'}) {
                    711: 	    return 1;
                    712: 	}
                    713: 	return 0;
                    714:     } elsif ($when eq 'wereopen') {
                    715: 	if ($time > $slot->{'endtime'}) {
                    716: 	    return 1;
                    717: 	}
                    718: 	return 0;
                    719:     }
                    720:     
                    721:     return 1;
                    722: }
                    723: 
1.33      albertel  724: sub remove_link {
                    725:     my ($slotname,$entry,$uname,$udom,$symb) = @_;
                    726: 
                    727:     $slotname  = &Apache::lonnet::escape($slotname);
                    728:     $entry     = &Apache::lonnet::escape($entry);
                    729:     $uname     = &Apache::lonnet::escape($uname);
                    730:     $udom      = &Apache::lonnet::escape($udom);
                    731:     $symb      = &Apache::lonnet::escape($symb);
                    732: 
                    733:     my $remove= &mt('Remove');
                    734: 
                    735:     return <<"END_LINK";
                    736:  <a href="/adm/slotrequest?command=remove_registration&slotname=$slotname&entry=$entry&uname=$uname&udom=$udom&symb=$symb"
                    737:    >($remove)</a>
                    738: END_LINK
                    739: 
                    740: }
                    741: 
1.5       albertel  742: sub show_table {
1.19      albertel  743:     my ($r,$mgr)=@_;
1.5       albertel  744: 
                    745:     my ($cnum,$cdom)=&get_course();
                    746:     my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum);
1.19      albertel  747:     if ( (keys(%slots))[0] =~ /^error: 2 /) {
                    748: 	undef(%slots);
                    749:     } 
1.5       albertel  750:     my $available;
1.14      albertel  751:     if ($mgr eq 'F') {
1.30      albertel  752: 	$r->print('<div>');
1.14      albertel  753: 	$r->print('<form method="POST" action="/adm/slotrequest">
                    754: <input type="hidden" name="command" value="uploadstart" />
                    755: <input type="submit" name="start" value="'.&mt('Upload Slot List').'" />
                    756: </form>');
1.28      albertel  757: 	$r->print('<form method="POST" action="/adm/helper/newslot.helper">
                    758: <input type="submit" name="newslot" value="'.&mt('Create a New Slot').'" />
                    759: </form>');
1.30      albertel  760: 	$r->print('</div>');
1.14      albertel  761:     }
1.29      albertel  762:     
1.35      albertel  763:     my %Saveable_Parameters = ('show'    => 'array',
                    764: 			       'when'    => 'scalar',
                    765: 			       'order'   => 'scalar',
                    766: 			       'deleted' => 'scalar',
                    767: 			       );
1.46      albertel  768:     &Apache::loncommon::store_course_settings('slotrequest',
                    769: 					      \%Saveable_Parameters);
                    770:     &Apache::loncommon::restore_course_settings('slotrequest',
                    771: 						\%Saveable_Parameters);
                    772:     &Apache::grades::init_perm();
                    773:     my ($classlist,$section,$fullname)=&Apache::grades::getclasslist('all');
                    774:     &Apache::grades::reset_perm();
1.29      albertel  775: 
1.30      albertel  776:     my %show_fields=&Apache::lonlocal::texthash(
1.49      albertel  777: 	     'name'            => 'Slot Name',
                    778: 	     'description'     => 'Description',
                    779: 	     'type'            => 'Type',
                    780: 	     'starttime'       => 'Start time',
                    781: 	     'endtime'         => 'End Time',
                    782:              'startreserve'    => 'Time students can start reserving',
                    783: 	     'secret'          => 'Secret Word',
                    784: 	     'maxspace'        => 'Maximum # of students',
                    785: 	     'ip'              => 'IP or DNS restrictions',
                    786: 	     'symb'            => 'Resource slot is restricted to.',
                    787: 	     'allowedsections' => 'Sections slot is restricted to.',
                    788: 	     'allowedusers'    => 'Users slot is restricted to.',
                    789: 	     'uniqueperiod'    => 'Period of time slot is unique',
                    790: 	     'scheduled'       => 'Scheduled Students',
                    791: 	     'proctor'         => 'List of proctors');
1.30      albertel  792:     my @show_order=('name','description','type','starttime','endtime',
1.49      albertel  793: 		    'startreserve','secret','maxspace','ip','symb',
                    794: 		    'allowedsections','allowedusers','uniqueperiod',
                    795: 		    'scheduled','proctor');
1.30      albertel  796:     my @show = 
1.29      albertel  797: 	(exists($env{'form.show'})) ? &Apache::loncommon::get_env_multiple('form.show')
1.30      albertel  798: 	                            : keys(%show_fields);
                    799:     my %show =  map { $_ => 1 } (@show);
                    800: 
                    801:     my %when_fields=&Apache::lonlocal::texthash(
1.35      albertel  802: 	     'now'      => 'Open now',
1.30      albertel  803: 	     'nextweek' => 'Open within the next week',
                    804: 	     'lastweek' => 'Were open last week',
                    805: 	     'willopen' => 'Will open later',
1.35      albertel  806: 	     'wereopen' => 'Were open',
                    807: 	     'any'      => 'Anytime',
                    808: 						);
                    809:     my @when_order=('any','now','nextweek','lastweek','willopen','wereopen');
1.30      albertel  810:     $when_fields{'select_form_order'} = \@when_order;
                    811:     my $when = 	(exists($env{'form.when'})) ? $env{'form.when'}
                    812:                                             : 'now';
1.29      albertel  813: 
1.46      albertel  814:     my %stu_display_fields=
                    815: 	&Apache::lonlocal::texthash('username' => 'User name',
                    816: 				    'fullname' => 'Full name',
                    817: 				    );
                    818:     my @stu_display_order=('fullname','username');
                    819:     my @stu_display = 
                    820: 	(exists($env{'form.studisplay'})) ? &Apache::loncommon::get_env_multiple('form.studisplay')
                    821: 	                                  : keys(%stu_display_fields);
                    822:     my %stu_display =  map { $_ => 1 } (@stu_display);
                    823: 
1.35      albertel  824:     my $hide_radio = 
                    825: 	&Apache::lonhtmlcommon::radio('deleted',$env{'form.deleted'},'hide');
                    826:     my $show_radio = 
                    827: 	&Apache::lonhtmlcommon::radio('deleted',$env{'form.deleted'},'show');
                    828: 	
1.29      albertel  829:     $r->print('<form method="POST" action="/adm/slotrequest">
1.30      albertel  830: <input type="hidden" name="command" value="showslots" />');
                    831:     $r->print('<div>');
1.35      albertel  832:     $r->print('<table class="inline">
                    833:       <tr><th>'.&mt('Show').'</th>
1.46      albertel  834:           <th>'.&mt('Student Display').'</th>
1.35      albertel  835:           <th>'.&mt('Open').'</th>
                    836:           <th>'.&mt('Options').'</th>
                    837:       </tr>
                    838:       <tr><td>'.&Apache::loncommon::multiple_select_form('show',\@show,6,\%show_fields,\@show_order).
                    839: 	      '</td>
1.46      albertel  840:            <td>
                    841:          '.&Apache::loncommon::multiple_select_form('studisplay',\@stu_display,
                    842: 						    6,\%stu_display_fields,
                    843: 						    \@stu_display_order).'
                    844:            </td>
1.35      albertel  845:            <td>'.&Apache::loncommon::select_form($when,'when',%when_fields).
                    846:           '</td>
                    847:            <td>
                    848:             <table>
                    849:               <tr>
                    850:                 <td rowspan="2">Deleted slots:</td>
                    851:                 <td><label>'.$show_radio.'Show</label></td>
                    852:               </tr>
                    853:               <tr>
                    854:                 <td><label>'.$hide_radio.'Hide</label></td>
                    855:               </tr>
                    856:             </table>
                    857: 	  </td>
                    858:        </tr>
                    859:     </table>');
1.30      albertel  860:     $r->print('</div>');
                    861:     $r->print('<p><input type="submit" name="start" value="'.&mt('Update Display').'" /></p>');
1.21      albertel  862:     my $linkstart='<a href="/adm/slotrequest?command=showslots&amp;order=';
1.30      albertel  863:     $r->print('<table class="thinborder">
1.10      albertel  864: <tr>
1.29      albertel  865:   <th></th>');
1.30      albertel  866:     foreach my $which (@show_order) {
                    867: 	if ($which ne 'proctor' && exists($show{$which})) {
                    868: 	    $r->print('<th>'.$linkstart.$which.'">'.$show_fields{$which}.'</a></th>');
1.29      albertel  869: 	}
                    870:     }
                    871: 
1.21      albertel  872:     my %name_cache;
                    873:     my $slotsort = sub {
1.49      albertel  874: 	if ($env{'form.order'}=~/^(type|description|endtime|startreserve|maxspace|ip|symb|allowedsections|allowedusers)$/) {
1.21      albertel  875: 	    if (lc($slots{$a}->{$env{'form.order'}})
                    876: 		ne lc($slots{$b}->{$env{'form.order'}})) {
                    877: 		return (lc($slots{$a}->{$env{'form.order'}}) 
                    878: 			cmp lc($slots{$b}->{$env{'form.order'}}));
                    879: 	    }
1.23      albertel  880: 	} elsif ($env{'form.order'} eq 'name') {
                    881: 	    if (lc($a) cmp lc($b)) {
                    882: 		return lc($a) cmp lc($b);
                    883: 	    }
1.29      albertel  884: 	} elsif ($env{'form.order'} eq 'uniqueperiod') {
1.21      albertel  885: 	    
                    886: 	    if ($slots{$a}->{'uniqueperiod'}[0] 
                    887: 		ne $slots{$b}->{'uniqueperiod'}[0]) {
                    888: 		return ($slots{$a}->{'uniqueperiod'}[0]
                    889: 			cmp $slots{$b}->{'uniqueperiod'}[0]);
                    890: 	    }
                    891: 	    if ($slots{$a}->{'uniqueperiod'}[1] 
                    892: 		ne $slots{$b}->{'uniqueperiod'}[1]) {
                    893: 		return ($slots{$a}->{'uniqueperiod'}[1]
                    894: 			cmp $slots{$b}->{'uniqueperiod'}[1]);
                    895: 	    }
                    896: 	}
                    897: 	return $slots{$a}->{'starttime'} <=> $slots{$b}->{'starttime'};
                    898:     };
                    899:     foreach my $slot (sort $slotsort (keys(%slots)))  {
1.35      albertel  900: 	if (!&to_show($slots{$slot},$when,$env{'form.deleted'})) { next; }
1.5       albertel  901: 	if (defined($slots{$slot}->{'type'})
                    902: 	    && $slots{$slot}->{'type'} ne 'schedulable_student') {
1.13      albertel  903: 	    #next;
1.5       albertel  904: 	}
                    905: 	my $description=&get_description($slot,$slots{$slot});
                    906: 	my $ids;
1.47      albertel  907: 	if (exists($show{'scheduled'})) {
                    908: 	    my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                    909: 					       "^$slot\0");
                    910: 	    my ($tmp)=%consumed;
                    911: 	    if ($tmp !~ /^error: /) {
                    912: 		foreach my $entry (sort(keys(%consumed))) {
                    913: 		    my (undef,$id)=split("\0",$entry);
                    914: 		    my ($uname,$udom) = split('@',$consumed{$entry}{'name'});
                    915: 		    $ids.= '<nobr>';
                    916: 		    foreach my $item (@stu_display_order) {
                    917: 			if ($stu_display{$item}) {
                    918: 			    if ($item eq 'fullname') {
                    919: 				$ids.=$fullname->{"$uname:$udom"}.' ';
                    920: 			    } elsif ($item eq 'username') {
                    921: 				$ids.="<tt>$uname\@$udom</tt> ";
                    922: 			    }
1.46      albertel  923: 			}
                    924: 		    }
1.47      albertel  925: 		    $ids.=&remove_link($slot,$entry,$uname,$udom,
                    926: 				       $consumed{$entry}{'symb'}).'</nobr><br />';
1.46      albertel  927: 		}
1.38      albertel  928: 	    }
1.5       albertel  929: 	}
1.33      albertel  930: 
1.24      albertel  931: 	my $start=($slots{$slot}->{'starttime'}?
                    932: 		   &Apache::lonlocal::locallocaltime($slots{$slot}->{'starttime'}):'');
                    933: 	my $end=($slots{$slot}->{'endtime'}?
                    934: 		 &Apache::lonlocal::locallocaltime($slots{$slot}->{'endtime'}):'');
1.28      albertel  935: 	my $start_reserve=($slots{$slot}->{'startreserve'}?
1.24      albertel  936: 			   &Apache::lonlocal::locallocaltime($slots{$slot}->{'startreserve'}):'');
                    937: 	
1.14      albertel  938: 	my $unique;
                    939: 	if (ref($slots{$slot}{'uniqueperiod'})) {
                    940: 	    $unique=localtime($slots{$slot}{'uniqueperiod'}[0]).','.
                    941: 		localtime($slots{$slot}{'uniqueperiod'}[1]);
                    942: 	}
1.33      albertel  943: 
1.29      albertel  944: 	my $title;
                    945: 	if (exists($slots{$slot}{'symb'})) {
                    946: 	    my (undef,undef,$res)=
                    947: 		&Apache::lonnet::decode_symb($slots{$slot}{'symb'});
                    948: 	    $res =   &Apache::lonnet::clutter($res);
                    949: 	    $title = &Apache::lonnet::gettitle($slots{$slot}{'symb'});
                    950: 	    $title='<a href="'.$res.'?symb='.$slots{$slot}{'symb'}.'">'.$title.'</a>';
                    951: 	}
1.33      albertel  952: 
1.49      albertel  953: 	my $allowedsections;
                    954: 	if (exists($show{'allowedsections'})) {
                    955: 	    $allowedsections = 
                    956: 		join(', ',sort(split(/\s*,\s*/,
                    957: 				     $slots{$slot}->{'allowedsections'})));
                    958: 	}
                    959: 
                    960: 	my @allowedusers;
                    961: 	if (exists($show{'allowedusers'})) {
                    962: 	    @allowedusers= map {
                    963: 		my ($uname,$udom)=split(/:/,$_);
                    964: 		my $fullname=$name_cache{$_};
                    965: 		if (!defined($fullname)) {
                    966: 		    $fullname = &Apache::loncommon::plainname($uname,$udom);
                    967: 		    $fullname =~s/\s/&nbsp;/g;
                    968: 		    $name_cache{$_} = $fullname;
                    969: 		}
                    970: 		&Apache::loncommon::aboutmewrapper($fullname,$uname,$udom);
                    971: 	    } (sort(split(/\s*,\s*/,$slots{$slot}->{'allowedusers'})));
                    972: 	}
                    973: 	my $allowedusers=join(', ',@allowedusers);
                    974: 	
1.29      albertel  975: 	my @proctors;
                    976: 	my $rowspan=1;
                    977: 	my $colspan=1;
1.30      albertel  978: 	if (exists($show{'proctor'})) {
1.29      albertel  979: 	    $rowspan=2;
                    980: 	    @proctors= map {
                    981: 		my ($uname,$udom)=split(/@/,$_);
                    982: 		my $fullname=$name_cache{$_};
                    983: 		if (!defined($fullname)) {
                    984: 		    $fullname = &Apache::loncommon::plainname($uname,$udom);
                    985: 		    $fullname =~s/\s/&nbsp;/g;
                    986: 		    $name_cache{$_} = $fullname;
                    987: 		}
                    988: 		&Apache::loncommon::aboutmewrapper($fullname,$uname,$udom);
                    989: 	    } (sort(split(/\s*,\s*/,$slots{$slot}->{'proctor'})));
                    990: 	}
1.20      albertel  991: 	my $proctors=join(', ',@proctors);
1.14      albertel  992: 
1.34      albertel  993: 	my $edit=(<<"EDITLINK");
1.31      albertel  994: <a href="/adm/helper/newslot.helper?name=$slot">Edit</a>
                    995: EDITLINK
1.34      albertel  996: 
                    997: 	my $delete=(<<"DELETELINK");
                    998: <a href="/adm/slotrequest?command=delete&slotname=$slot">Delete</a>
                    999: DELETELINK
                   1000:         if ($ids ne '') { undef($delete); }
                   1001: 
                   1002:         $r->print("<tr>\n<td rowspan=\"$rowspan\">$edit $delete</td>\n");
1.30      albertel 1003: 	if (exists($show{'name'})) {
1.29      albertel 1004: 	    $colspan++;$r->print("<td>$slot</td>");
                   1005: 	}
1.33      albertel 1006: 	if (exists($show{'description'})) {
                   1007: 	    $colspan++;$r->print("<td>$description</td>\n");
                   1008: 	}
1.30      albertel 1009: 	if (exists($show{'type'})) {
1.29      albertel 1010: 	    $colspan++;$r->print("<td>$slots{$slot}->{'type'}</td>\n");
                   1011: 	}
1.30      albertel 1012: 	if (exists($show{'starttime'})) {
1.29      albertel 1013: 	    $colspan++;$r->print("<td>$start</td>\n");
                   1014: 	}
1.30      albertel 1015: 	if (exists($show{'endtime'})) {
1.29      albertel 1016: 	    $colspan++;$r->print("<td>$end</td>\n");
                   1017: 	}
1.30      albertel 1018: 	if (exists($show{'startreserve'})) {
1.29      albertel 1019: 	    $colspan++;$r->print("<td>$start_reserve</td>\n");
                   1020: 	}
1.30      albertel 1021: 	if (exists($show{'secret'})) {
1.29      albertel 1022: 	    $colspan++;$r->print("<td>$slots{$slot}{'secret'}</td>\n");
                   1023: 	}
1.30      albertel 1024: 	if (exists($show{'maxspace'})) {
1.29      albertel 1025: 	    $colspan++;$r->print("<td>$slots{$slot}{'maxspace'}</td>\n");
                   1026: 	}
1.30      albertel 1027: 	if (exists($show{'ip'})) {
1.29      albertel 1028: 	    $colspan++;$r->print("<td>$slots{$slot}{'ip'}</td>\n");
                   1029: 	}
1.30      albertel 1030: 	if (exists($show{'symb'})) {
1.29      albertel 1031: 	    $colspan++;$r->print("<td>$title</td>\n");
                   1032: 	}
1.49      albertel 1033: 	if (exists($show{'allowedsections'})) {
                   1034: 	    $colspan++;$r->print("<td>$allowedsections</td>\n");
                   1035: 	}
                   1036: 	if (exists($show{'allowedusers'})) {
                   1037: 	    $colspan++;$r->print("<td>$allowedusers</td>\n");
1.29      albertel 1038: 	}
1.47      albertel 1039: 	if (exists($show{'scheduled'})) {
                   1040: 	    $colspan++;$r->print("<td>$ids</td>\n</tr>\n");
                   1041: 	}
1.30      albertel 1042: 	if (exists($show{'proctor'})) {
1.29      albertel 1043: 	    $r->print(<<STUFF);
1.21      albertel 1044: <tr>
1.29      albertel 1045:  <td colspan="$colspan">$proctors</td>
1.21      albertel 1046: </tr>
1.5       albertel 1047: STUFF
1.29      albertel 1048:         }
1.5       albertel 1049:     }
                   1050:     $r->print('</table>');
                   1051: }
                   1052: 
1.14      albertel 1053: sub upload_start {
1.19      albertel 1054:     my ($r)=@_;    
1.14      albertel 1055:     $r->print(&Apache::grades::checkforfile_js());
                   1056:     my $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";
                   1057:     $result.='&nbsp;<b>'.
                   1058: 	&mt('Specify a file containing the slot definitions.').
                   1059: 	'</b></td></tr>'."\n";
                   1060:     $result.='<tr bgcolor=#ffffe6><td>'."\n";
                   1061:     my $upfile_select=&Apache::loncommon::upfile_select_html();
                   1062:     my $ignore=&mt('Ignore First Line');
                   1063:     $result.=<<ENDUPFORM;
                   1064: <form method="post" enctype="multipart/form-data" action="/adm/slotrequest" name="slotupload">
                   1065: <input type="hidden" name="command" value="csvuploadmap" />
                   1066: $upfile_select
                   1067: <br /><input type="button" onClick="javascript:checkUpload(this.form);" value="Upload Data" />
                   1068: <label><input type="checkbox" name="noFirstLine" />$ignore</label>
                   1069: </form>
                   1070: ENDUPFORM
                   1071:     $result.='</td></tr></table>'."\n";
                   1072:     $result.='</td></tr></table>'."\n";
                   1073:     $r->print($result);
                   1074: }
                   1075: 
                   1076: sub csvuploadmap_header {
1.19      albertel 1077:     my ($r,$datatoken,$distotal)= @_;
1.14      albertel 1078:     my $javascript;
                   1079:     if ($env{'form.upfile_associate'} eq 'reverse') {
                   1080: 	$javascript=&csvupload_javascript_reverse_associate();
                   1081:     } else {
                   1082: 	$javascript=&csvupload_javascript_forward_associate();
                   1083:     }
                   1084: 
                   1085:     my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');
                   1086:     my $ignore=&mt('Ignore First Line');
                   1087:     $r->print(<<ENDPICK);
                   1088: <form method="post" enctype="multipart/form-data" action="/adm/slotrequest" name="slotupload">
                   1089: <h3>Identify fields</h3>
                   1090: Total number of records found in file: $distotal <hr />
                   1091: Enter as many fields as you can. The system will inform you and bring you back
                   1092: to this page if the data selected is insufficient to create the slots.<hr />
                   1093: <input type="button" value="Reverse Association" onClick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />
                   1094: <label><input type="checkbox" name="noFirstLine" $checked />$ignore</label>
                   1095: <input type="hidden" name="associate"  value="" />
                   1096: <input type="hidden" name="datatoken"  value="$datatoken" />
                   1097: <input type="hidden" name="fileupload" value="$env{'form.fileupload'}" />
                   1098: <input type="hidden" name="upfiletype" value="$env{'form.upfiletype'}" />
                   1099: <input type="hidden" name="upfile_associate" 
                   1100:                                        value="$env{'form.upfile_associate'}" />
                   1101: <input type="hidden" name="command"    value="csvuploadassign" />
                   1102: <hr />
                   1103: <script type="text/javascript" language="Javascript">
                   1104: $javascript
                   1105: </script>
                   1106: ENDPICK
                   1107:     return '';
                   1108: 
                   1109: }
                   1110: 
                   1111: sub csvuploadmap_footer {
                   1112:     my ($request,$i,$keyfields) =@_;
                   1113:     $request->print(<<ENDPICK);
                   1114: </table>
                   1115: <input type="hidden" name="nfields" value="$i" />
                   1116: <input type="hidden" name="keyfields" value="$keyfields" />
                   1117: <input type="button" onClick="javascript:verify(this.form)" value="Create Slots" /><br />
                   1118: </form>
                   1119: ENDPICK
                   1120: }
                   1121: 
                   1122: sub csvupload_javascript_reverse_associate {
                   1123:     my $error1=&mt('You need to specify the name, starttime, endtime and a type');
                   1124:     return(<<ENDPICK);
                   1125:   function verify(vf) {
                   1126:     var foundstart=0;
                   1127:     var foundend=0;
                   1128:     var foundname=0;
                   1129:     var foundtype=0;
                   1130:     for (i=0;i<=vf.nfields.value;i++) {
                   1131:       tw=eval('vf.f'+i+'.selectedIndex');
                   1132:       if (i==0 && tw!=0) { foundname=1; }
                   1133:       if (i==1 && tw!=0) { foundtype=1; }
                   1134:       if (i==2 && tw!=0) { foundstat=1; }
                   1135:       if (i==3 && tw!=0) { foundend=1; }
                   1136:     }
                   1137:     if (foundstart==0 && foundend==0 && foundtype==0 && foundname==0) {
                   1138: 	alert('$error1');
                   1139: 	return;
                   1140:     }
                   1141:     vf.submit();
                   1142:   }
                   1143:   function flip(vf,tf) {
                   1144:   }
                   1145: ENDPICK
                   1146: }
                   1147: 
                   1148: sub csvupload_javascript_forward_associate {
                   1149:     my $error1=&mt('You need to specify the name, starttime, endtime and a type');
                   1150:   return(<<ENDPICK);
                   1151:   function verify(vf) {
                   1152:     var foundstart=0;
                   1153:     var foundend=0;
                   1154:     var foundname=0;
                   1155:     var foundtype=0;
                   1156:     for (i=0;i<=vf.nfields.value;i++) {
                   1157:       tw=eval('vf.f'+i+'.selectedIndex');
                   1158:       if (tw==1) { foundname=1; }
                   1159:       if (tw==2) { foundtype=1; }
                   1160:       if (tw==3) { foundstat=1; }
                   1161:       if (tw==4) { foundend=1; }
                   1162:     }
                   1163:     if (foundstart==0 && foundend==0 && foundtype==0 && foundname==0) {
                   1164: 	alert('$error1');
                   1165: 	return;
                   1166:     }
                   1167:     vf.submit();
                   1168:   }
                   1169:   function flip(vf,tf) {
                   1170:   }
                   1171: ENDPICK
                   1172: }
                   1173: 
                   1174: sub csv_upload_map {
1.19      albertel 1175:     my ($r)= @_;
1.14      albertel 1176: 
                   1177:     my $datatoken;
                   1178:     if (!$env{'form.datatoken'}) {
                   1179: 	$datatoken=&Apache::loncommon::upfile_store($r);
                   1180:     } else {
                   1181: 	$datatoken=$env{'form.datatoken'};
                   1182: 	&Apache::loncommon::load_tmp_file($r);
                   1183:     }
                   1184:     my @records=&Apache::loncommon::upfile_record_sep();
                   1185:     if ($env{'form.noFirstLine'}) { shift(@records); }
1.19      albertel 1186:     &csvuploadmap_header($r,$datatoken,$#records+1);
1.14      albertel 1187:     my ($i,$keyfields);
                   1188:     if (@records) {
                   1189: 	my @fields=&csvupload_fields();
                   1190: 
                   1191: 	if ($env{'form.upfile_associate'} eq 'reverse') {	
                   1192: 	    &Apache::loncommon::csv_print_samples($r,\@records);
                   1193: 	    $i=&Apache::loncommon::csv_print_select_table($r,\@records,
                   1194: 							  \@fields);
                   1195: 	    foreach (@fields) { $keyfields.=$_->[0].','; }
                   1196: 	    chop($keyfields);
                   1197: 	} else {
                   1198: 	    unshift(@fields,['none','']);
                   1199: 	    $i=&Apache::loncommon::csv_samples_select_table($r,\@records,
                   1200: 							    \@fields);
                   1201: 	    my %sone=&Apache::loncommon::record_sep($records[0]);
                   1202: 	    $keyfields=join(',',sort(keys(%sone)));
                   1203: 	}
                   1204:     }
                   1205:     &csvuploadmap_footer($r,$i,$keyfields);
                   1206: 
                   1207:     return '';
                   1208: }
                   1209: 
                   1210: sub csvupload_fields {
                   1211:     return (['name','Slot name'],
                   1212: 	    ['type','Type of slot'],
                   1213: 	    ['starttime','Start Time of slot'],
                   1214: 	    ['endtime','End Time of slot'],
1.15      albertel 1215: 	    ['startreserve','Reservation Start Time'],
1.14      albertel 1216: 	    ['ip','IP or DNS restriction'],
                   1217: 	    ['proctor','List of proctor ids'],
                   1218: 	    ['description','Slot Description'],
                   1219: 	    ['maxspace','Maximum number of reservations'],
                   1220: 	    ['symb','Resource Restriction'],
                   1221: 	    ['uniqueperiod','Date range of slot exclusion'],
1.49      albertel 1222: 	    ['secret','Secret word proctor uses to validate'],
                   1223: 	    ['allowedsections','Sections slot is restricted to'],
                   1224: 	    ['allowedusers','Users slot is restricted to'],
                   1225: 	    );
1.14      albertel 1226: }
                   1227: 
                   1228: sub csv_upload_assign {
1.19      albertel 1229:     my ($r,$mgr)= @_;
1.14      albertel 1230:     &Apache::loncommon::load_tmp_file($r);
                   1231:     my @slotdata = &Apache::loncommon::upfile_record_sep();
                   1232:     if ($env{'form.noFirstLine'}) { shift(@slotdata); }
                   1233:     my %fields=&Apache::grades::get_fields();
                   1234:     $r->print('<h3>Creating Slots</h3>');
                   1235:     my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};
                   1236:     my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
                   1237:     my $countdone=0;
1.31      albertel 1238:     my @errors;
1.14      albertel 1239:     foreach my $slot (@slotdata) {
                   1240: 	my %slot;
                   1241: 	my %entries=&Apache::loncommon::record_sep($slot);
                   1242: 	my $domain;
                   1243: 	my $name=$entries{$fields{'name'}};
1.31      albertel 1244: 	if ($name=~/^\s*$/) {
                   1245: 	    push(@errors,"Did not create slot with no name");
                   1246: 	    next;
                   1247: 	}
                   1248: 	if ($name=~/\s/) { 
                   1249: 	    push(@errors,"$name not created -- Name must not contain spaces");
                   1250: 	    next;
                   1251: 	}
                   1252: 	if ($name=~/\W/) { 
                   1253: 	    push(@errors,"$name not created -- Name must contain only letters, numbers and _");
                   1254: 	    next;
                   1255: 	}
1.14      albertel 1256: 	if ($entries{$fields{'type'}}) {
                   1257: 	    $slot{'type'}=$entries{$fields{'type'}};
                   1258: 	} else {
                   1259: 	    $slot{'type'}='preassigned';
                   1260: 	}
1.31      albertel 1261: 	if ($slot{'type'} ne 'preassigned' &&
                   1262: 	    $slot{'type'} ne 'schedulable_student') {
                   1263: 	    push(@errors,"$name not created -- invalid type ($slot{'type'}) must be either preassigned or schedulable_student");
                   1264: 	    next;
                   1265: 	}
1.14      albertel 1266: 	if ($entries{$fields{'starttime'}}) {
                   1267: 	    $slot{'starttime'}=&UnixDate($entries{$fields{'starttime'}},"%s");
                   1268: 	}
                   1269: 	if ($entries{$fields{'endtime'}}) {
1.16      albertel 1270: 	    $slot{'endtime'}=&UnixDate($entries{$fields{'endtime'}},"%s");
1.14      albertel 1271: 	}
1.23      albertel 1272: 	if ($entries{$fields{'startreserve'}}) {
                   1273: 	    $slot{'startreserve'}=
                   1274: 		&UnixDate($entries{$fields{'startreserve'}},"%s");
                   1275: 	}
1.14      albertel 1276: 	foreach my $key ('ip','proctor','description','maxspace',
                   1277: 			 'secret','symb') {
                   1278: 	    if ($entries{$fields{$key}}) {
                   1279: 		$slot{$key}=$entries{$fields{$key}};
                   1280: 	    }
                   1281: 	}
                   1282: 	if ($entries{$fields{'uniqueperiod'}}) {
                   1283: 	    my ($start,$end)=split(',',$entries{$fields{'uniqueperiod'}});
                   1284: 	    my @times=(&UnixDate($start,"%s"),
                   1285: 		       &UnixDate($end,"%s"));
                   1286: 	    $slot{'uniqueperiod'}=\@times;
                   1287: 	}
                   1288: 
                   1289: 	&Apache::lonnet::cput('slots',{$name=>\%slot},$cdom,$cname);
                   1290: 	$r->print('.');
                   1291: 	$r->rflush();
                   1292: 	$countdone++;
                   1293:     }
1.31      albertel 1294:     $r->print("<p>Created $countdone slots\n</p>");
                   1295:     foreach my $error (@errors) {
                   1296: 	$r->print("<p>$error\n</p>");
                   1297:     }
1.19      albertel 1298:     &show_table($r,$mgr);
1.14      albertel 1299:     return '';
                   1300: }
                   1301: 
1.1       albertel 1302: sub handler {
                   1303:     my $r=shift;
                   1304: 
1.30      albertel 1305:     &Apache::loncommon::content_type($r,'text/html');
                   1306:     &Apache::loncommon::no_cache($r);
                   1307:     if ($r->header_only()) {
                   1308: 	$r->send_http_header();
                   1309: 	return OK;
                   1310:     }
                   1311: 
1.8       albertel 1312:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
1.28      albertel 1313:     
1.12      albertel 1314:     my $vgr=&Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.14      albertel 1315:     my $mgr=&Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.28      albertel 1316:     my $title='Requesting Another Worktime';
                   1317:     if ($env{'form.command'} =~ /^(showslots|uploadstart|csvuploadmap|csvuploadassign)$/ && $vgr eq 'F') {
                   1318: 	$title = 'Managing Slots';
                   1319:     }
                   1320:     &start_page($r,$title);
                   1321: 
1.8       albertel 1322:     if ($env{'form.command'} eq 'showslots' && $vgr eq 'F') {
1.19      albertel 1323: 	&show_table($r,$mgr);
1.33      albertel 1324:     } elsif ($env{'form.command'} eq 'remove_registration' && $mgr eq 'F') {
                   1325: 	&remove_registration($r);
                   1326:     } elsif ($env{'form.command'} eq 'release' && $mgr eq 'F') {
                   1327: 	&release_slot($r,undef,undef,undef,$mgr);
1.34      albertel 1328:     } elsif ($env{'form.command'} eq 'delete' && $mgr eq 'F') {
                   1329: 	&delete_slot($r);
1.14      albertel 1330:     } elsif ($env{'form.command'} eq 'uploadstart' && $mgr eq 'F') {
1.19      albertel 1331: 	&upload_start($r);
1.14      albertel 1332:     } elsif ($env{'form.command'} eq 'csvuploadmap' && $mgr eq 'F') {
1.19      albertel 1333: 	&csv_upload_map($r);
1.14      albertel 1334:     } elsif ($env{'form.command'} eq 'csvuploadassign' && $mgr eq 'F') {
                   1335: 	if ($env{'form.associate'} ne 'Reverse Association') {
1.19      albertel 1336: 	    &csv_upload_assign($r,$mgr);
1.14      albertel 1337: 	} else {
                   1338: 	    if ( $env{'form.upfile_associate'} ne 'reverse' ) {
                   1339: 		$env{'form.upfile_associate'} = 'reverse';
                   1340: 	    } else {
                   1341: 		$env{'form.upfile_associate'} = 'forward';
                   1342: 	    }
1.19      albertel 1343: 	    &csv_upload_map($r);
1.14      albertel 1344: 	}
1.8       albertel 1345:     } else {
1.19      albertel 1346: 	my $symb=&Apache::lonnet::unescape($env{'form.symb'});
                   1347: 	my (undef,undef,$res)=&Apache::lonnet::decode_symb($symb);
1.36      albertel 1348: 	my $useslots = &Apache::lonnet::EXT("resource.0.useslots",$symb);
                   1349: 	if ($useslots ne 'resource') {
1.19      albertel 1350: 	    &fail($r,'not_valid');
                   1351: 	    return OK;
                   1352: 	}
                   1353: 	$env{'request.symb'}=$symb;
1.36      albertel 1354: 	my $type = ($res =~ /\.task$/) ? 'Task'
                   1355: 	                               : 'problem';
                   1356: 	my ($status) = &Apache::lonhomework::check_slot_access('0',$type);
1.11      albertel 1357: 	if ($status eq 'CAN_ANSWER' ||
                   1358: 	    $status eq 'NEEDS_CHECKIN' ||
                   1359: 	    $status eq 'WAITING_FOR_GRADE') {
                   1360: 	    &fail($r,'not_allowed');
                   1361: 	    return OK;
                   1362: 	}
                   1363: 	if ($env{'form.requestattempt'}) {
                   1364: 	    &show_choices($r,$symb);
                   1365: 	} elsif ($env{'form.command'} eq 'release') {
                   1366: 	    &release_slot($r,$symb);
                   1367: 	} elsif ($env{'form.command'} eq 'get') {
                   1368: 	    &get_slot($r,$symb);
                   1369: 	} elsif ($env{'form.command'} eq 'change') {
1.39      albertel 1370: 	    if (&release_slot($r,$symb,$env{'form.releaseslot'},1)) {
                   1371: 		&get_slot($r,$symb);
                   1372: 	    }
1.11      albertel 1373: 	} else {
                   1374: 	    $r->print("<p>Unknown command: ".$env{'form.command'}."</p>");
                   1375: 	}
1.2       albertel 1376:     }
1.1       albertel 1377:     &end_page($r);
                   1378:     return OK;
                   1379: }
1.3       albertel 1380: 
                   1381: 1;
                   1382: __END__

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.