--- loncom/interface/slotrequest.pm 2010/06/06 02:40:30 1.108 +++ loncom/interface/slotrequest.pm 2018/06/24 04:11:08 1.138 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler for requesting to have slots added to a students record # -# $Id: slotrequest.pm,v 1.108 2010/06/06 02:40:30 raeburn Exp $ +# $Id: slotrequest.pm,v 1.138 2018/06/24 04:11:08 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -37,7 +37,7 @@ use Apache::lonnet; use Apache::lonnavmaps(); use Date::Manip; use lib '/home/httpd/lib/perl/'; -use LONCAPA; +use LONCAPA qw(:DEFAULT :match); sub fail { my ($r,$code)=@_; @@ -56,12 +56,22 @@ sub fail { } sub start_page { - my ($r,$title,$brcrum)=@_; + my ($r,$title,$brcrum,$js)=@_; my $args; if (ref($brcrum) eq 'ARRAY') { $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 { @@ -69,6 +79,291 @@ sub 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"; + +ENDSCRIPT + +} + + =pod slot_reservations db @@ -121,7 +416,6 @@ sub check_for_reservation { my ($symb,$mode)=@_; my $student = &Apache::lonnet::EXT("resource.0.availablestudent", $symb, $env{'user.domain'}, $env{'user.name'}); - my $course = &Apache::lonnet::EXT("resource.0.available", $symb, $env{'user.domain'}, $env{'user.name'}); my @slots = (split(/:/,$student), split(/:/, $course)); @@ -137,16 +431,20 @@ sub check_for_reservation { return 'error: Unable to determine current status'; } 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) { next if (!defined($slots{$slot_name}) || !ref($slots{$slot_name})); &Apache::lonxml::debug(time." $slot_name ". $slots{$slot_name}->{'starttime'}." -- ". - $slots{$slot_name}->{'startreserve'}); - if ($slots{$slot_name}->{'endtime'} > time && - $slots{$slot_name}->{'startreserve'} < time) { - # between start of reservation times and end of slot + $slots{$slot_name}->{'startreserve'}." -- ". + $slots{$slot_name}->{'endreserve'}); + if (($slots{$slot_name}->{'endtime'} > time) && + ($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') { push(@got,$slot_name); } else { @@ -167,7 +465,7 @@ sub get_consumed_uniqueperiods { return 'error: Unable to determine current status'; } my @problems = $navmap->retrieveResources(undef, - sub { $_[0]->is_problem() },1,0); + sub { $_[0]->is_problem() || $_[0]->is_tool() },1,0); my %used_slots; foreach my $problem (@problems) { my $symb = $problem->symb(); @@ -214,16 +512,19 @@ sub check_for_conflict { if (!defined($new_slot->{'uniqueperiod'})) { return undef; } if (!ref($consumed_uniqueperiods)) { - $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'; - } + if ($consumed_uniqueperiods =~ /^error: /) { + return $consumed_uniqueperiods; } 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'}}; foreach my $slot_name (keys(%$consumed_uniqueperiods)) { my ($start,$end)=@{$consumed_uniqueperiods->{$slot_name}}; @@ -335,12 +636,12 @@ sub store_slot_parm { context => $env{'form.context'}, ); - &Apache::lonnet::instructor_log('slotreservationslog',\%storehash, - '',$env{'user.name'},$env{'user.domain'}, - $cnum,$cdom); - &Apache::lonnet::instructor_log($cdom.'_'.$cnum.'_slotlog',\%storehash, - 1,$env{'user.name'},$env{'user.domain'}, - $env{'user.name'},$env{'user.domain'}); + &Apache::lonnet::write_log('course','slotreservationslog',\%storehash, + '',$env{'user.name'},$env{'user.domain'}, + $cnum,$cdom); + &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash, + 1,$env{'user.name'},$env{'user.domain'}, + $env{'user.name'},$env{'user.domain'}); return; } @@ -500,14 +801,20 @@ sub release_reservation { return (0,'error: Unable to determine current status'); } my $passed_resource = $navmap->getBySymb($symb); - if ($passed_resource->is_map()) { - my ($a_resource) = - $navmap->retrieveResources($passed_resource, - sub {$_[0]->is_problem()},0,1); - $symb = $a_resource->symb(); + if (ref($passed_resource)) { + if ($passed_resource->is_map()) { + my ($a_resource) = + $navmap->retrieveResources($passed_resource, + 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", $symb,$udom,$uname); my @slots = split(/:/,$student); @@ -534,10 +841,10 @@ sub release_reservation { action => 'release', context => $env{'form.context'}, ); - &Apache::lonnet::instructor_log('slotreservationslog',\%storehash, - 1,$uname,$udom,$cnum,$cdom); - &Apache::lonnet::instructor_log($cdom.'_'.$cnum.'_slotlog',\%storehash, - 1,$uname,$udom,$uname,$udom); + &Apache::lonnet::write_log('slotreservationslog',\%storehash, + 1,$uname,$udom,$cnum,$cdom); + &Apache::lonnet::write_log($cdom.'_'.$cnum.'_slotlog',\%storehash, + 1,$uname,$udom,$uname,$udom); } } @@ -562,7 +869,11 @@ sub release_reservation { if ($mgr eq 'F') { $msg = &mt('Released Reservation for user: [_1]',"$uname:$udom"); } else { - $msg = &mt('Released Reservation: [_1]',$description); + $msg = ''.&mt('Released reservation: [_1]',$description).'

'; + my $person = &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'}); + my $subject = &mt('Reservation change: [_1]',$description); + my $msgbody = &mt('Reservation released by [_1] for [_2].',$person,$description); + $msg .= &slot_change_messaging($slot{'reservationmsg'},$subject,$msgbody,'release'); } return (1,$msg); } @@ -627,10 +938,15 @@ sub get_slot { if ($slot_name && $slot_name ne $conflictable_slot) { my %slot=&Apache::lonnet::get_slot($slot_name); my $description1=&get_description($slot_name,\%slot); + my $slottype1=$slot{'type'}; %slot=&Apache::lonnet::get_slot($env{'form.slotname'}); my $description2=&get_description($env{'form.slotname'},\%slot); - $r->print('

'.&mt('Already have a reservation: [_1].',$description1).'

'); - if ($slot_name ne $env{'form.slotname'}) { + if ($slottype1 eq 'preassigned') { + $r->print('

'.&mt('You already have a reservation: "[_1]", assigned by your instructor.', + $description1).'

'. + '

'.&mt('Your instructor must unassign it before you can make a new reservation.'). + '

'); + } elsif ($slot_name ne $env{'form.slotname'}) { $r->print(< @@ -638,19 +954,24 @@ sub get_slot { STUFF - $r->print('

' - .&mt('You can either [_1]Change[_2] your reservation from [_3] to [_4] or' - ,'' - ,''.$description1.'' - ,''.$description2.'') - .'

' - ); - &return_link($r); + $r->print('

'.&mt('Reservation currently unchanged').'

'); + if ($slot_name ne '') { + $r->print('

'.&mt('To complete the transaction you [_1]must confirm[_2] you want to [_3]process the change[_4] to [_5].' + ,'','','','',''.$description2.'') + .'
' + .&mt('Or you can choose to [_1]make no change[_2] and continue[_2] with the reservation you already had: [_3].' + ,'','',''.$description1.'') + .'

' + .'' + .(' 'x3) + .'' + .'

'); + } $r->print(< STUFF } else { + $r->print('

'.&mt('Already have a reservation: [_1].',$description1).'

'); &return_link($r); } return 0; @@ -667,8 +988,15 @@ STUFF .&mt('An error occurred while attempting to make a reservation. ([_1])',$1) .'

'); } elsif ($reserved > -1) { - $r->print('

'.&mt('Success: [_1]',$description).'

'); + $r->print('

'.&mt('Successfully signed up: [_1]',$description).'

'); $retvalue = 1; + my $person = &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'}); + my $subject = &mt('Reservation change: [_1]',$description); + my $msgbody = &mt('Successful reservation by [_1] for [_2].',$person,$description); + my $msg = &slot_change_messaging($slot{'reservationmsg'},$subject,$msgbody,'reserve'); + if ($msg) { + $r->print($msg); + } } elsif ($reserved < 0) { $r->print('

'.&mt('Already reserved: [_1]',$description).'

'); } @@ -677,7 +1005,7 @@ STUFF } my %lt = &Apache::lonlocal::texthash( - 'request' => 'Availibility list', + 'request' => 'Availability list', 'try' => 'Try again?', 'or' => 'or', ); @@ -716,7 +1044,7 @@ STUFF } sub allowed_slot { - my ($slot_name,$slot,$symb,$slots,$consumed_uniqueperiods)=@_; + my ($slot_name,$slot,$symb,$slots,$consumed_uniqueperiods,$toskip)=@_; #already started if ($slot->{'starttime'} < time) { @@ -741,6 +1069,11 @@ sub allowed_slot { if ($slot->{'startreserve'} > time) { return 0; } + # reserve time ended + if (($slot->{'endreserve'}) && + ($slot->{'endreserve'} < time)) { + return 0; + } &Apache::lonxml::debug("$slot_name reserve good"); my $userallowed=0; @@ -785,9 +1118,33 @@ sub allowed_slot { return 0 if (!$userallowed); # not allowed for this resource - if (defined($slot->{'symb'}) - && $slot->{'symb'} ne $symb) { - return 0; + if (defined($slot->{'symb'})) { + my $exclude = 1; + 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, @@ -815,76 +1172,119 @@ sub get_description { } sub show_choices { - my ($r,$symb,$formname)=@_; - - 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(''. - &mt('An error occurred determining slot availability'). - ''); - return; - } - } elsif ($consumed_uniqueperiods =~ /^error: /) { - $r->print(''. - &mt('An error occurred determining slot availability'). - ''); - return; - } - my (@available,$output); + my ($symb,$formname,$num,$class,$slots,$consumed_uniqueperiods,$available,$got_slots)=@_; + my $output; &Apache::lonxml::debug("Checking Slots"); - my @got_slots=&check_for_reservation($symb,'allslots'); - if ($got_slots[0] =~ /^error: /) { - $r->print(''. - &mt('An error occurred determining slot availability'). - ''); + if (!ref($available) eq 'ARRAY') { return; } - foreach my $slot (sort - { return $slots{$a}->{'starttime'} <=> $slots{$b}->{'starttime'} } - (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 (!@{$available}) { + $output = ''.&mt('No available times.').''; if ($env{'form.command'} ne 'manageresv') { $output .= ' '. &mt('Return to last resource').''; } - $r->print($output); - return; + if ($class) { + return '
'.$output.'
'; + } 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 .= '
'.&mt('Actions').''."\n". + '
'; + 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 .= ''.(' ' x3)."\n"; + } + $output .= '
'; + my $chooserform = 'reservationchooser_'.$num; + my $starttime = $slots->{$available->[0]}->{'starttime'}; + my $endtime = $slots->{$available->[-1]}->{'starttime'}; + if ($env{'form.command'} eq 'manageresv') { + $output .= <<"ENDSCRIPT"; + + + +ENDSCRIPT + } + $output .= + '
'. + '
'. + '
'.&mt('Open after').''. + &Apache::lonhtmlcommon::date_setter($chooserform,'start',$starttime,'','','','','','','',1,1). + '
'.&mt('Closed before').''. + &Apache::lonhtmlcommon::date_setter($chooserform,'end',$endtime,'','','','','','','',1,1). + '

'. + ''. + '
'; + } + if ($class) { + return '
'.$output.'
'; + } else { + return $output; } - $r->print($output); } sub to_show { @@ -1034,7 +1442,8 @@ sub show_table { my $available; if ($mgr eq 'F') { # FIXME: This line should be deleted once Slots uses breadcrumbs - $r->print(&Apache::loncommon::help_open_topic('Slot About', 'Help on slots')); + $r->print('
'.&Apache::loncommon::help_open_topic( + 'Slot About', &mt('Help on slots'))); $r->print('
'); $r->print(' @@ -1050,11 +1459,11 @@ sub show_table { } if (!keys(%slots)) { - if ($crstype eq 'Community') { - $r->print('
'.&mt('No slots have been created in this community.').'
'); - } else { - $r->print('
'.&mt('No slots have been created in this course.').'
'); - } + $r->print( + '

' + .&mt('No slots have been created in this '.lc($crstype).'.') + .'

' + ); return; } @@ -1081,22 +1490,26 @@ sub show_table { 'starttime' => 'Start time', 'endtime' => 'End Time', 'startreserve' => 'Time students can start reserving', + 'endreserve' => 'Time students can no longer reserve', + 'reservationmsg' => 'Message triggered by reservation', 'secret' => 'Secret Word', 'space' => '# of students/max', '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.', 'allowedusers' => 'Users slot is restricted to.', 'uniqueperiod' => 'Period of time slot is unique', 'scheduled' => 'Scheduled Students', - 'proctor' => 'List of proctors'); + 'proctor' => 'List of proctors', + 'iptied' => 'Unique IP each student',); if ($crstype eq 'Community') { $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'); } my @show_order=('name','description','type','starttime','endtime', - 'startreserve','secret','space','ip','symb', - 'allowedsections','allowedusers','uniqueperiod', + 'startreserve','endreserve','reservationmsg','secret','space', + 'ip','iptied','symb','allowedsections','allowedusers','uniqueperiod', 'scheduled','proctor'); my @show = (exists($env{'form.show'})) ? &Apache::loncommon::get_env_multiple('form.show') @@ -1182,11 +1595,11 @@ sub show_table { - - + + - +
Deleted slots:'.&mt('Deleted slots:').'
@@ -1195,19 +1608,20 @@ sub show_table { $r->print('
'); $r->print('

'); my $linkstart=''.$show_fields{$which}.''); + $tableheader .= ''.$linkstart.$which.'">'.$show_fields{$which}.''; } } - $r->print(&Apache::loncommon::end_data_table_header_row()); + $tableheader .= &Apache::loncommon::end_data_table_header_row(); + my $shownheader = 0; my %name_cache; my $slotsort = sub { - if ($env{'form.order'}=~/^(type|description|endtime|startreserve|ip|symb|allowedsections|allowedusers)$/) { + if ($env{'form.order'}=~/^(type|description|endtime|startreserve|endreserve|ip|symb|allowedsections|allowedusers|reservationmsg)$/) { if (lc($slots{$a}->{$env{'form.order'}}) ne lc($slots{$b}->{$env{'form.order'}})) { return (lc($slots{$a}->{$env{'form.order'}}) @@ -1244,12 +1658,15 @@ sub show_table { if ($tmp =~ /^error: /) { undef(%consumed); } } + my %msgops = &slot_reservationmsg_options(); + foreach my $slot (sort $slotsort (keys(%slots))) { if (!&to_show($slot,$slots{$slot},$when, $env{'form.deleted'},$name_filter)) { next; } + my $reservemsg; if (defined($slots{$slot}->{'type'}) - && $slots{$slot}->{'type'} ne 'schedulable_student') { - #next; + && $slots{$slot}->{'type'} eq 'schedulable_student') { + $reservemsg = $msgops{$slots{$slot}->{'reservationmsg'}}; } my $description=&get_description($slot,$slots{$slot}); my ($id_count,$ids); @@ -1286,6 +1703,8 @@ sub show_table { &Apache::lonlocal::locallocaltime($slots{$slot}->{'endtime'}):''); my $start_reserve=($slots{$slot}->{'startreserve'}? &Apache::lonlocal::locallocaltime($slots{$slot}->{'startreserve'}):''); + my $end_reserve=($slots{$slot}->{'endreserve'}? + &Apache::lonlocal::locallocaltime($slots{$slot}->{'endreserve'}):''); my $unique; if (ref($slots{$slot}{'uniqueperiod'})) { @@ -1293,13 +1712,21 @@ sub show_table { localtime($slots{$slot}{'uniqueperiod'}[1]); } - my $title; + my @titles; if (exists($slots{$slot}{'symb'})) { - my (undef,undef,$res)= - &Apache::lonnet::decode_symb($slots{$slot}{'symb'}); - $res = &Apache::lonnet::clutter($res); - $title = &Apache::lonnet::gettitle($slots{$slot}{'symb'}); - $title=''.$title.''; + my @symbs; + if ($slots{$slot}{'symb'} =~ /,/) { + @symbs = split(/\s*,\s*/,$slots{$slot}{'symb'}); + } else { + @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,''.$title.''); + } } my $allowedsections; @@ -1347,30 +1774,39 @@ sub show_table { delete => 'Delete', slotlog => 'History', ); - my $edit=(<<"EDITLINK"); + my ($edit,$delete,$showlog,$remove_all); + if ($mgr) { + $edit=(<<"EDITLINK"); $lt{'edit'} EDITLINK - my $delete=(<<"DELETELINK"); + $delete=(<<"DELETELINK"); $lt{'delete'} DELETELINK - my $showlog=(<<"LOGLINK"); + $remove_all=&remove_link($slot,'remove all').'
'; + + if ($ids eq '') { + undef($remove_all); + } else { + undef($delete); + } + } + + $showlog=(<<"LOGLINK"); $lt{'slotlog'} LOGLINK - my $remove_all=&remove_link($slot,'remove all').'
'; - - if ($ids eq '') { - undef($remove_all); - } else { - undef($delete); - } if ($slots{$slot}{'type'} ne 'schedulable_student') { undef($showlog); undef($remove_all); } + unless ($shownheader) { + $r->print($tableheader); + $shownheader = 1; + } + my $row_start=&Apache::loncommon::start_data_table_row(); my $row_end=&Apache::loncommon::end_data_table_row(); $r->print($row_start. @@ -1393,6 +1829,12 @@ LOGLINK if (exists($show{'startreserve'})) { $colspan++;$r->print("$start_reserve\n"); } + if (exists($show{'endreserve'})) { + $colspan++;$r->print("$end_reserve\n"); + } + if (exists($show{'reservationmsg'})) { + $colspan++;$r->print("$reservemsg\n"); + } if (exists($show{'secret'})) { $colspan++;$r->print("$slots{$slot}{'secret'}\n"); } @@ -1409,8 +1851,18 @@ LOGLINK if (exists($show{'ip'})) { $colspan++;$r->print("$slots{$slot}{'ip'}\n"); } + if (exists($show{'iptied'})) { + $colspan++; + if ($slots{$slot}{'iptied'} eq 'yes') { + $r->print(''.&mt('Yes')."\n"); + } elsif ($slots{$slot}{'iptied'} eq 'answer') { + $r->print(''.&mt('Yes, including post-answer date')."\n"); + } else { + $r->print(''.&mt('No')."\n"); + } + } if (exists($show{'symb'})) { - $colspan++;$r->print("$title\n"); + $colspan++;$r->print("".join('
',@titles)."\n"); } if (exists($show{'allowedsections'})) { $colspan++;$r->print("$allowedsections\n"); @@ -1433,12 +1885,18 @@ $row_end STUFF } } - $r->print(&Apache::loncommon::end_data_table().''); + if ($shownheader) { + $r->print(&Apache::loncommon::end_data_table()); + } else { + $r->print('

'.&mt('No slots meet the criteria for display').'

'); + } + $r->print(''); return; } sub manage_reservations { - my ($r,$crstype) = @_; + my ($r,$crstype,$slots,$consumed_uniqueperiods,$allavailable) = @_; + my ($cnum,$cdom)=&get_course(); my $navmap = Apache::lonnavmaps::navmap->new(); $r->print('

' .&mt('Instructors may use a reservation system to place restrictions on when and where assignments can be worked on.') @@ -1457,154 +1915,246 @@ sub manage_reservations { &Apache::lonnet::logthis('Manage Reservations - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'}); return; } - my (%parent,%shownparent,%container,%container_title,%contents); - my ($depth,$count,$reservable,$lastcontainer,$rownum) = (0,0,0,0,0); - my @backgrounds = ("LC_odd_row","LC_even_row"); + if (ref($consumed_uniqueperiods) eq 'HASH') { + if (&Apache::lonnet::error(%$consumed_uniqueperiods)) { + $r->print(''. + &mt('An error occurred determining slot availability.'). + ''); + return; + } + } elsif ($consumed_uniqueperiods =~ /^error: /) { + $r->print(''. + &mt('An error occurred determining slot availability.'). + ''); + 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=''.&mt('Reserved:'). + ' '.$slotdescription.'
'. + &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=''.&mt('Reserved:'). + ' '.$slotdescription.'
'. + &mt('Problem is currently available.'); + } elsif ($slot_status == $resource->RESERVED_LOCATION) { + $msg=''.&mt('Reserved:'). + ' '.$slotdescription.'
'. + &mt('Problem is available at a different location.'); + $get_choices = 1; + } elsif ($slot_status == $resource->RESERVED_LATER) { + $msg=''.&mt('Reserved:'). + ' '.$slotdescription.'
'. + &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 $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace_21.gif"); my $slotheader = '

'. &mt('Your reservation status for any such assignments is listed below:'). '

'. - ''."\n"; + '
'."\n"; my $shownheader = 0; + my $currmap; my $it=$navmap->getIterator(undef,undef,undef,1,undef,undef); while (my $resource = $it->next()) { if ($resource == $it->BEGIN_MAP()) { $depth++; - $parent{$depth} = $lastcontainer; - } - if ($resource == $it->END_MAP()) { - $depth--; - $lastcontainer = $parent{$depth}; - } - if (ref($resource)) { - my $symb = $resource->symb(); - 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=''.&mt('Reserved:'). - ' '.$slotdescription.'
'. - &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=''.&mt('Reserved:'). - ' '.$slotdescription.'
'. - &mt('Problem is currently available.'); - } elsif ($slot_status == $resource->RESERVED_LOCATION) { - $msg=''.&mt('Reserved:'). - ' '.$slotdescription.'
'. - &mt('Problem is available at a different location.'); - $get_choices = 1; - } elsif ($slot_status == $resource->RESERVED_LATER) { - $msg=''.&mt('Reserved:'). - ' '.$slotdescription.'
'. - &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'); - } + $parent{$depth} = $currcontainer; + if (ref($container{$currcontainer})) { + my $currmapres = $container{$currcontainer}; + my $currmaptitle = $container_title{$currcontainer}; + $currmap = $currmapres->src(); + my $currmaptype = 'sequence'; + if ($currmapres->is_page()) { + $currmaptype = 'page'; } - $reservable ++; - my $treelevel = $depth; - my $higherup = $lastcontainer; - if ($depth > 1) { - my @maprows; - while ($treelevel > 1) { - if (ref($container{$higherup})) { - 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}; + if ($shownmaps{$currmap}) { + $mapnum ++; + $rownum ++; + $shown ++; + if (!$shownheader) { + $r->print($slotheader); + $shownheader = 1; } - foreach my $item (@maprows) { - $rownum ++; - my $bgcolor = $backgrounds[$rownum % $numcolors]; - if (!$shownheader) { - $r->print($slotheader); - $shownheader = 1; + my $bgcolor = $backgrounds[$shown % $numcolors]; + my ($spacers,$icon); + my $row = ''; + if (ref($statusbymap{$currmap}) eq 'HASH') { + my ($spacers,$icon) = &show_map_row($depth-1,$location,$currmaptype,$currmaptitle); + my $arrowstate = 'open'; + if (keys(%{$statusbymap{$currmap}}) == 1) { + $arrowstate = 'closed'; } - $r->print(''.$item.''."\n"); + $row .= ''."\n"; + if (ref($output{$currmap}) eq 'HASH') { + my $formnum = $mapnum.'_'.$reservable+1; + my $class = 'LC_slotmaptext_'.$mapnum; + if ($output{$currmap}{'hasaction'}) { + $row .= ''; + } else { + $row .= ''; + } + $row .= ''."\n"; + } else { + $row .= ''."\n"; + } + } else { + my ($spacers,$icon) = &show_map_row($depth,$location,$currmaptype,$currmaptitle); + $row .= ''."\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 ++; - my $bgcolor = $backgrounds[$rownum % $numcolors]; if (!$shownheader) { $r->print($slotheader); $shownheader = 1; } - $r->print(''. + ''; - my $hasaction; - if ($status == $resource->OPEN) { - if ($get_choices) { - $hasaction = 1; - } + $r->print('problem.gif" alt="'.&mt('Problem')); } - if ($hasaction) { - $result .= ''. - ''); + my $class = 'LC_slottext_'.$mapnum; + if ($output{$symb}{'hasaction'}) { + $r->print(''. + ''); } else { - $result .= ''; + $r->print(''); } - $r->print($result); - if ($hasaction) { - my $formname = 'manageres_'.$reservable; - &show_choices($r,$symb,$formname); - $r->print(''); - } - $r->print(''); + $r->print(''."\n"); } } } @@ -1625,19 +2175,68 @@ sub manage_reservations { } sub show_map_row { - my ($depth,$location,$type,$title,$maprows) = @_; - my $output = ''."\n"; - unshift (@{$maprows},$output); - return; + $icon .= $title; + return ($spacers,$icon); +} + +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 = ''. + &mt('An error occurred determining slot availability.'). + ''; + } 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 { @@ -1649,8 +2248,7 @@ sub show_reservations { $udom = $env{'user.domain'}; } my $formname = 'slotlog'; - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my ($cnum,$cdom)=&get_course(); my $crstype = &Apache::loncommon::course_type(); my %log=&Apache::lonnet::dump('nohist_'.$cdom.'_'.$cnum.'_slotlog',$udom,$uname); if ($env{'form.origin'} eq 'aboutme') { @@ -1751,16 +2349,19 @@ sub show_reservations { if ($showntablehdr) { $r->print(&Apache::loncommon::end_data_table().'
'); if (($curr{'page'} > 1) || ($more_records)) { - $r->print('
'.$spacers.''. + $icon.(' ' x6).''. + $output{$currmap}{'msg'}. + ''. + &slot_chooser($repsymbs{$currmap},$class,$formnum, + $allavailable,$slots,$consumed_uniqueperiods). + ''. + $output{$currmap}{'msg'}. + '
 
'.$spacers.$icon.(' ' x6).' 
'."\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('
'); for (my $i=0; $i<$depth; $i++) { $r->print(''); } - my $result = ''. - 'src().'?symb='.$symb.'">'. + ''.&mt('Task');
+                    $r->print('task.gif'.$title.''.(' ' x6).''.$msg.''.(' ' x6); + $r->print('" />'.$title.''.(' ' x6).''.$output{$symb}{'msg'}.''. + &slot_chooser($symb,$class,$reservable,$allavailable,$slots, + $consumed_uniqueperiods).''.$msg.''. + ''.$output{$symb}{'msg'}.''. + '
'; + my ($depth,$location,$type,$title) = @_; + my $spacers; for (my $i=0; $i<$depth-1; $i++) { - $output .= ''; + $spacers .= ''; } + my $icon; if ($type eq 'page') { - $output .= ' '."\n"; + $icon = ' '."\n"; } else { - $output .= ' '."\n"; + $icon = ' '."\n"; } - $output .= $title.' 
'); + $r->print('

'); if ($curr{'page'} > 1) { - $r->print('

'); + $r->print(''); } if ($more_records) { - $r->print(''); + $r->print(''); } - $r->print('
'.&mt('Previous [_1] changes',$curr{'show'}).''.&mt('Next [_1] changes',$curr{'show'}).'
'); + $r->print('

'); $r->print(<<"ENDSCRIPT"); ENDSCRIPT } @@ -1821,8 +2423,7 @@ sub show_reservations_log { return; } my $formname = 'reservationslog'; - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my ($cnum,$cdom)=&get_course(); my %slotlog=&Apache::lonnet::dump('nohist_slotreservationslog',$cdom,$cnum); if ((keys(%slotlog))[0]=~/^error\:/) { undef(%slotlog); } @@ -1960,14 +2561,16 @@ sub show_reservations_log { if ($showntablehdr) { $r->print(&Apache::loncommon::end_data_table().'
'); if (($curr{'page'} > 1) || ($more_records)) { - $r->print(''); + $r->print('

'); if ($curr{'page'} > 1) { - $r->print('

'); + $r->print(''); } if ($more_records) { - $r->print(''); + $r->print(''); } - $r->print('
'.&mt('Previous [_1] changes',$curr{'show'}).''.&mt('Next [_1] changes',$curr{'show'}).'
'); + $r->print('

'); $r->print(<<"ENDSCRIPT"); ENDPICK return ''; @@ -2187,7 +2852,6 @@ sub csvuploadmap_footer { my ($request,$i,$keyfields) =@_; my $buttontext = &mt('Create Slots'); $request->print(<
@@ -2196,7 +2860,7 @@ ENDPICK } 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(< $slot{'starttime'}) { @@ -2370,20 +3046,85 @@ sub csv_upload_assign { 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 ($entries{$fields{'reservationmsg'}}) { + if (($entries{$fields{'reservationmsg'}} eq 'only_student') || + ($entries{$fields{'reservationmsg'}} eq 'student_and_user_notes_screen')) { + $slot{'reservationmsg'}=$entries{$fields{'reservationmsg'}}; + } else { + unless (($entries{$fields{'reservationmsg'}} eq 'none') || + ($entries{$fields{'reservationmsg'}} eq '')) { + push(@errors,"$name -- Slot's reservationmsg setting ignored - not one of: 'only_student', 'student_and_user_notes_screen', 'none' or ''"); + } + } + } + } + foreach my $key ('ip','proctor','description','maxspace', 'secret','symb') { if ($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'}}) { - my ($start,$end)=split(',',$entries{$fields{'uniqueperiod'}}); - my @times=(&UnixDate($start,"%s"), - &UnixDate($end,"%s")); - $slot{'uniqueperiod'}=\@times; + my ($start,$end)= map { &UnixDate($_,"%s"); } split(',',$entries{$fields{'uniqueperiod'}}); + if (($start ne '') && ($end ne '')) { + $slot{'uniqueperiod'}=[$start,$end]; + } 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]) { push(@errors,"$name not created -- Slot's unique period start time is later than the unique period's end time."); next; @@ -2394,6 +3135,9 @@ sub csv_upload_assign { $r->rflush(); $countdone++; } + if ($countdone) { + &Apache::lonnet::devalidate_slots_cache($cname,$cdom); + } $r->print('

'.&mt('Created [quant,_1,slot]',$countdone)."\n".'

'); foreach my $error (@errors) { $r->print('

'.$error.'

'."\n"); @@ -2419,6 +3163,15 @@ sub slot_command_titles { return %titles; } +sub slot_reservationmsg_options { + my %options = &Apache::lonlocal::texthash ( + only_student => 'Sent to student', + student_and_user_notes_screen => 'Sent to student and added to user notes', + none => 'None sent and no record in user notes', + ); + return %options; +} + sub handler { my $r=shift; @@ -2436,6 +3189,7 @@ sub handler { my $vgr=&Apache::lonnet::allowed('vgr',$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 (($vgr ne 'F') && ($mgr ne 'F')) { $env{'form.command'} = 'manageresv'; @@ -2456,9 +3210,14 @@ sub handler { if (ref($brcrum) eq 'ARRAY') { push(@{$brcrum},{href=>"/adm/slotrequest?command=showresv",text=>$title}); } - } elsif ($env{'form.command'} eq 'manageresv') { - $title = 'Manage Reservations'; - $brcrum =[{href=>"/adm/slotrequest?command=manageresv",text=>$title}]; + } elsif (($env{'form.requestattempt'}) || ($env{'form.command'} eq 'manageresv')) { + if ($env{'form.command'} eq 'manageresv') { + $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') { if ($env{'form.command'} =~ /^(slotlog|showslots|uploadstart|csvuploadmap|csvuploadassign|delete|release|remove_registration)$/) { $brcrum =[{href=>"/adm/slotrequest?command=showslots", @@ -2478,14 +3237,27 @@ sub handler { if (ref($brcrum) eq 'ARRAY') { push(@{$brcrum},{href=>"/adm/slotrequest?command=$env{'form.command'}",text=>$crumb_titles{$env{'form.command'}}}); } - } + } else { + $brcrum =[]; } - &start_page($r,$title,$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,$js); if ($env{'form.command'} eq 'manageresv') { + $allavailable = $available; + undef($available); + undef($got_slots); my $crstype = &Apache::loncommon::course_type(); - &manage_reservations($r,$crstype); + &manage_reservations($r,$crstype,\%slots,$consumed_uniqueperiods,$allavailable); } elsif ($env{'form.command'} eq 'showresv') { &show_reservations($r,$env{'form.uname'},$env{'form.udom'}); } elsif ($env{'form.command'} eq 'showslots' && $vgr eq 'F') { @@ -2515,7 +3287,7 @@ sub handler { } &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); } else { my $symb=&unescape($env{'form.symb'}); @@ -2537,18 +3309,40 @@ sub handler { my ($status) = &Apache::lonhomework::check_slot_access('0',$type); if ($status eq 'CAN_ANSWER' || $status eq 'NEEDS_CHECKIN' || - $status eq 'WAITING_FOR_GRADE') { + $status eq 'WAITING_FOR_GRADE' || + $status eq 'NEED_DIFFERENT_IP') { &fail($r,'not_allowed'); return OK; } if ($env{'form.requestattempt'}) { - &show_choices($r,$symb); + $r->print('
'); + $r->print(&show_choices($symb,undef,undef,undef,\%slots,$consumed_uniqueperiods,$available,$got_slots)); + $r->print('
'); } elsif ($env{'form.command'} eq 'release') { &release_slot($r,$symb); } elsif ($env{'form.command'} eq 'get') { &get_slot($r,$symb); } elsif ($env{'form.command'} eq 'change') { - if (&get_slot($r,$symb,$env{'form.releaseslot'},1)) { + if ($env{'form.nochange'}) { + my $slot_name = $env{'form.releaseslot'}; + my @slots = &check_for_reservation($symb,'allslots'); + my $msg; + if (($slot_name ne '') && (grep(/^\Q$slot_name\E/,@slots))) { + my %slot=&Apache::lonnet::get_slot($env{'form.releaseslot'}); + my $description=&get_description($slot_name,\%slot); + $msg = ''. + &mt('Unchanged reservation: [_1]',$description).'

'; + my $person = + &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'}); + my $subject = &mt('Reservation unchanged: [_1]',$description); + my $msgbody = &mt('No change to existing registration by [_1] for [_2].',$person,$description); + $msg .= &slot_change_messaging($slot{'reservationmsg'},$subject,$msgbody,'nochange'); + } else { + $msg = ''.&mt('Reservation no longer reported as available.').''; + } + $r->print($msg); + &return_link($r); + } elsif (&get_slot($r,$symb,$env{'form.releaseslot'},1)) { &release_slot($r,$symb,$env{'form.releaseslot'}); } } else { 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.