--- loncom/interface/slotrequest.pm 2009/05/17 21:03:16 1.88.2.1 +++ loncom/interface/slotrequest.pm 2009/05/06 16:19:34 1.97 @@ -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.88.2.1 2009/05/17 21:03:16 raeburn Exp $ +# $Id: slotrequest.pm,v 1.97 2009/05/06 16:19:34 bisitz Exp $ # # Copyright Michigan State University Board of Trustees # @@ -56,8 +56,12 @@ sub fail { } sub start_page { - my ($r,$title)=@_; - $r->print(&Apache::loncommon::start_page($title)); + my ($r,$title,$brcrum)=@_; + my $args; + if (ref($brcrum) eq 'ARRAY') { + $args = {bread_crumbs => $brcrum}; + } + $r->print(&Apache::loncommon::start_page($title,undef,$args)); } sub end_page { @@ -133,14 +137,8 @@ sub check_for_reservation { return 'error: Unable to determine current status'; } my @got; - foreach my $slot_name (sort { - if (ref($slots{$a}) && ref($slots{$b})) { - return $slots{$a}{'starttime'} <=> $slots{$b}{'starttime'} - } - if (ref($slots{$a})) { return -1;} - if (ref($slots{$b})) { return 1;} - return 0; - } @slots) { + my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots); + foreach my $slot_name (@sorted_slots) { next if (!defined($slots{$slot_name}) || !ref($slots{$slot_name})); &Apache::lonxml::debug(time." $slot_name ". @@ -239,9 +237,7 @@ sub check_for_conflict { } sub make_reservation { - my ($slot_name,$slot,$symb)=@_; - - my ($cnum,$cdom)=&get_course(); + my ($slot_name,$slot,$symb,$cnum,$cdom)=@_; my $value=&Apache::lonnet::EXT("resource.0.availablestudent",$symb, $env{'user.domain'},$env{'user.name'}); @@ -315,13 +311,7 @@ sub make_reservation { if ($value) { $new_value=$value.':'.$new_value; } - my $result=&Apache::lonparmset::storeparm_by_symb($symb, - '0_availablestudent', - $parm_level, $new_value, - 'string', - $env{'user.name'}, - $env{'user.domain'}); - &Apache::lonxml::debug("hrrm $result"); + &store_slot_parm($symb,$slot_name,$parm_level,$new_value,$cnum,$cdom); return $wanted; } @@ -329,6 +319,32 @@ sub make_reservation { return undef; } +sub store_slot_parm { + my ($symb,$slot_name,$parm_level,$new_value,$cnum,$cdom) = @_; + my $result=&Apache::lonparmset::storeparm_by_symb($symb, + '0_availablestudent', + $parm_level, $new_value, + 'string', + $env{'user.name'}, + $env{'user.domain'}); + &Apache::lonxml::debug("hrrm $result"); + my %storehash = ( + symb => $symb, + slot => $slot_name, + action => 'reserve', + 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'}); + + return; +} + sub remove_registration { my ($r) = @_; if ($env{'form.entry'} ne 'remove all') { @@ -354,7 +370,7 @@ sub remove_registration { my $names = join(' ',@names); my $msg = &mt('Remove all of [_1] from slot [_2]?',$names,$slot_name); - &remove_registration_confirmation($r,$msg,['entry','slotname']); + &remove_registration_confirmation($r,$msg,['entry','slotname','context']); } sub remove_registration_user { @@ -371,7 +387,7 @@ sub remove_registration_user { $name,$slot_name,$title); &remove_registration_confirmation($r,$msg,['uname','udom','slotname', - 'entry','symb']); + 'entry','symb','context']); } sub remove_registration_confirmation { @@ -383,8 +399,10 @@ sub remove_registration_confirmation { '&\'').'" />'."\n"; } - my %lt = &Apache::lonlocal::texthash('yes' => 'Yes', - 'no' => 'No',); + my %lt = &Apache::lonlocal::texthash( + 'yes' => 'Yes', + 'no' => 'No', + ); $r->print(<<"END_CONFIRM");

$msg

@@ -510,6 +528,16 @@ sub release_reservation { if ( $consumed{$entry}->{'name'} eq ($uname.':'.$udom) ) { &Apache::lonnet::del('slot_reservations',[$entry], $cdom,$cnum); + my %storehash = ( + symb => $symb, + slot => $slot_name, + 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); } } @@ -530,7 +558,6 @@ sub release_reservation { '0_availablestudent', $parm_level, $new_param, 'string', $uname, $udom); - my $msg; if ($mgr eq 'F') { $msg = &mt('Released Reservation for user: [_1]',"$uname:$udom"); @@ -575,8 +602,13 @@ sub delete_slot { sub return_link { my ($r) = @_; - $r->print('

'. - &mt('Return to last resource').'

'); + if (($env{'form.command'} eq 'manageresv') || ($env{'form.context'} eq 'usermanage')) { + $r->print('

'. + &mt('Return to reservations')); + } else { + $r->print('

'. + &mt('Return to last resource').'

'); + } } sub get_slot { @@ -624,8 +656,9 @@ STUFF return 0; } + my ($cnum,$cdom)=&get_course(); my $reserved=&make_reservation($env{'form.slotname'}, - \%slot,$symb); + \%slot,$symb,$cnum,$cdom); my $description=&get_description($env{'form.slotname'},\%slot); if (defined($reserved)) { my $retvalue = 0; @@ -643,10 +676,11 @@ STUFF return 1; } - my %lt=('request'=>"Availibility list", - 'try' =>'Try again?', - 'or' => 'or'); - %lt=&Apache::lonlocal::texthash(%lt); + my %lt = &Apache::lonlocal::texthash( + 'request' => 'Availibility list', + 'try' => 'Try again?', + 'or' => 'or', + ); my $extra_input; if ($conflictable_slot) { @@ -673,8 +707,7 @@ $lt{'or'} STUFF if (!$inhibit_return_link) { - $r->print(&mt('or').'

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

').&return_link($r); } else { $r->print('

'); } @@ -781,7 +814,7 @@ sub get_description { } sub show_choices { - my ($r,$symb)=@_; + my ($r,$symb,$formname)=@_; my ($cnum,$cdom)=&get_course(); my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum); @@ -799,7 +832,7 @@ sub show_choices { ''); return; } - my $available; + my (@available,$output); &Apache::lonxml::debug("Checking Slots"); my @got_slots=&check_for_reservation($symb,'allslots'); if ($got_slots[0] =~ /^error: /) { @@ -808,7 +841,6 @@ sub show_choices { ''); return; } - $r->print(''); foreach my $slot (sort { return $slots{$a}->{'starttime'} <=> $slots{$b}->{'starttime'} } (keys(%slots))) { @@ -817,11 +849,25 @@ sub show_choices { next if (!&allowed_slot($slot,$slots{$slot},undef,\%slots, $consumed_uniqueperiods)); - $available++; - + push(@available,$slot); + } + if (!@available) { + $output = &mt('No available times.'); + if ($env{'form.command'} ne 'manageresv') { + $output .= ' '. + &mt('Return to last resource').''; + } + $r->print($output); + return; + } + if ($env{'form.command'} eq 'manageresv') { + $output = '
'; + } else { + $output = &Apache::loncommon::start_data_table(); + } + foreach my $slot (@available) { my $description=&get_description($slot,$slots{$slot}); - - my $form=&mt('Unavailable'); + my $form; if ((grep(/^\Q$slot\E$/,@got_slots)) || &space_available($slot,$slots{$slot},$symb)) { my $text=&mt('Select'); @@ -835,9 +881,9 @@ sub show_choices { $consumed_uniqueperiods); if ($conflict) { if ($conflict =~ /^error: /) { - $r->print(''); + $form = ''. + &mt('Slot: [_1] has unknown status.',$description). + ''; } else { $text=&mt('Change Reservation'); $command='get'; @@ -845,29 +891,47 @@ sub show_choices { } } my $escsymb=&escape($symb); - $form=< + if (!$form) { + if ($formname) { + $formname = 'name="'.$formname.'" '; + } + my $context = 'user'; + if ($env{'form.command'} eq 'manageresv') { + $context = 'usermanage'; + } + $form=< + STUFF - } - $r->print(< + } + } else { + $form = &mt('Unavailable'); + } + if ($env{'form.command'} eq 'manageresv') { + $output .= ''; + } else { + $output .= &Apache::loncommon::start_data_table_row(); + } + $output .= " - - -STUFF + \n"; + if ($env{'form.command'} eq 'manageresv') { + $output .= ''; + } else { + $output .= &Apache::loncommon::end_data_table_row(); + } } - - if (!$available) { - $r->print(''); + if ($env{'form.command'} eq 'manageresv') { + $output .= '
' - .&mt('Slot: [_1] has unknown status.',$description) - .'
$form$description
$description
'.&mt('No available times.'). - ' '. - &mt('Return to last resource').'
'; + } else { + $output .= &Apache::loncommon::end_data_table(); } - $r->print(''); + $r->print($output); } sub to_show { @@ -951,7 +1015,7 @@ sub remove_link { $symb = &escape($symb); return <<"END_LINK"; - ($remove) END_LINK @@ -982,6 +1046,11 @@ sub show_table { $r->print(&Apache::loncommon::help_open_topic('Slot AddInterface')); $r->print(''); } + + if (!keys(%slots)) { + $r->print('
'.&mt('No slots have been created in this course.').'
'); + return; + } my %Saveable_Parameters = ('show' => 'array', 'when' => 'scalar', @@ -1083,16 +1152,16 @@ sub show_table { '.&mt('Slot Name Filter').' '.&mt('Options').' - '.&Apache::loncommon::multiple_select_form('show',\@show,6,\%show_fields,\@show_order). + '.&Apache::loncommon::multiple_select_form('show',\@show,6,\%show_fields,\@show_order). ' - + '.&Apache::loncommon::multiple_select_form('studisplay',\@stu_display, 6,\%stu_display_fields, \@stu_display_order).' - '.&Apache::loncommon::select_form($when,'when',%when_fields). + '.&Apache::loncommon::select_form($when,'when',%when_fields). ' - '.&Apache::loncommon::select_form($name_filter_type, + '.&Apache::loncommon::select_form($name_filter_type, 'name_filter_type', %name_filter_type_fields). '
'. @@ -1100,7 +1169,7 @@ sub show_table { $env{'form.name_filter_value'}, 15). ' - + @@ -1263,26 +1332,39 @@ sub show_table { } my $proctors=join(', ',@proctors); + my %lt = &Apache::lonlocal::texthash ( + edit => 'Edit', + delete => 'Delete', + slotlog => 'History', + ); my $edit=(<<"EDITLINK"); -Edit +$lt{'edit'} EDITLINK my $delete=(<<"DELETELINK"); -Delete +$lt{'delete'} DELETELINK + my $showlog=(<<"LOGLINK"); +$lt{'slotlog'} +LOGLINK + my $remove_all=&remove_link($slot,'remove all').'
'; - if ($ids ne '') { undef($delete); } - if ($slots{$slot}{'type'} ne 'schedulable_student' - || $ids eq '') { + if ($ids eq '') { + undef($remove_all); + } else { + undef($delete); + } + if ($slots{$slot}{'type'} ne 'schedulable_student') { + undef($showlog); undef($remove_all); } my $row_start=&Apache::loncommon::start_data_table_row(); my $row_end=&Apache::loncommon::end_data_table_row(); $r->print($row_start. - "\n\n"); + "\n\n"); if (exists($show{'name'})) { $colspan++;$r->print(""); } @@ -1341,13 +1423,647 @@ $row_end STUFF } } - $r->print('
Deleted slots:$edit $delete$edit $delete $showlog$slot
'); + $r->print(&Apache::loncommon::end_data_table().''); + return; +} + +sub manage_reservations { + my ($r,$type) = @_; + 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.') + .'
' + .&mt('One example is for management of laboratory space, which is only available at certain times, and has a limited number of seats.') + .'

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

' + ); + if (!defined($navmap)) { + $r->print('
'. + &mt('Unable to retrieve information about course contents'). + '
'); + &Apache::lonnet::logthis('Manage Reservations - could not create navmap object in '.lc($type).':'.$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"); + my $numcolors = scalar(@backgrounds); + my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace_21.gif"); + $r->print(''."\n"); + 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'); + } + } + $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}; + } + foreach my $item (@maprows) { + $rownum ++; + my $bgcolor = $backgrounds[$rownum % $numcolors]; + $r->print(''.$item.''."\n"); + } + } + $rownum ++; + my $bgcolor = $backgrounds[$rownum % $numcolors]; + $r->print(''; + my $hasaction; + if ($status == $resource->OPEN) { + if ($get_choices) { + $hasaction = 1; + } + } + if ($hasaction) { + $result .= ''. + ''; + } + $r->print($result); + if ($hasaction) { + my $formname = 'manageres_'.$reservable; + &show_choices($r,$symb,$formname); + $r->print(''); + } + $r->print(''); + } + } + } + if (!$reservable) { + $r->print(''.&mt('No course items currently require a reservation to gain access.').''); + } + $r->print('
'."\n"); + for (my $i=0; $i<$depth; $i++) { + $r->print(''); + } + my $result = ''. + ''.&mt('Task');
+                } else {
+                    $result .= 'problem.gif'.$title.''.(' ' x6).''.$msg.''.(' ' x6); + } else { + $result .= ''.$msg.'
'. + '

'. + &mt('Reservation History').'

'); +} + +sub show_map_row { + my ($depth,$location,$type,$title,$maprows) = @_; + my $output = ''; + for (my $i=0; $i<$depth-1; $i++) { + $output .= ''; + } + if ($type eq 'page') { + $output .= ' '."\n"; + } else { + $output .= ' '."\n"; + } + $output .= $title.' '."\n"; + unshift (@{$maprows},$output); + return; +} + +sub show_reservations { + my ($r,$uname,$udom) = @_; + if (!defined($uname)) { + $uname = $env{'user.name'}; + } + if (!defined($udom)) { + $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 %log=&Apache::lonnet::dump('nohist_'.$cdom.'_'.$cnum.'_slotlog',$udom,$uname); + if ($env{'form.origin'} eq 'aboutme') { + $r->print('
'. + &mt('History of student-reservable slots for: [_1]', + &Apache::loncommon::plainname($env{'form.uname'},$env{'form.udom'}, + 'firstname')).'
'); + } + $r->print('
'); + # set defaults + my $now = time(); + my $defstart = $now - (7*24*3600); #7 days ago + my %defaults = ( + page => '1', + show => '10', + action => 'any', + log_start_date => $defstart, + log_end_date => $now, + ); + my $more_records = 0; + + # set current + my %curr; + foreach my $item ('show','page','action') { + $curr{$item} = $env{'form.'.$item}; + } + my ($startdate,$enddate) = + &Apache::lonuserutils::get_dates_from_form('log_start_date', + 'log_end_date'); + $curr{'log_start_date'} = $startdate; + $curr{'log_end_date'} = $enddate; + foreach my $key (keys(%defaults)) { + if ($curr{$key} eq '') { + $curr{$key} = $defaults{$key}; + } + } + my ($version) = ($r->dir_config('lonVersion') =~ /^([\d\.]+)\-/); + $r->print(&display_filter($formname,$cdom,$cnum,\%curr,$version)); + my $showntablehdr = 0; + my $tablehdr = &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + ' '.&mt('When').''.&mt('Action').''. + ''.&mt('Description').''.&mt('Start time').''. + ''.&mt('End time').''.&mt('Resource').''. + &Apache::loncommon::end_data_table_header_row(); + my ($minshown,$maxshown); + $minshown = 1; + my $count = 0; + if ($curr{'show'} ne &mt('all')) { + $maxshown = $curr{'page'} * $curr{'show'}; + if ($curr{'page'} > 1) { + $minshown = 1 + ($curr{'page'} - 1) * $curr{'show'}; + } + } + my (%titles,%maptitles); + my %lt = &reservationlog_contexts(); + foreach my $id (sort { $log{$b}{'exe_time'}<=>$log{$a}{'exe_time'} } (keys(%log))) { + next if (($log{$id}{'exe_time'} < $curr{'log_start_date'}) || + ($log{$id}{'exe_time'} > $curr{'log_end_date'})); + if ($curr{'show'} ne &mt('all')) { + if ($count >= $curr{'page'} * $curr{'show'}) { + $more_records = 1; + last; + } + } + if ($curr{'action'} ne 'any') { + next if ($log{$id}{'logentry'}{'action'} ne $curr{'action'}); + } + $count ++; + next if ($count < $minshown); + if (!$showntablehdr) { + $r->print($tablehdr); + $showntablehdr = 1; + } + my $symb = $log{$id}{'logentry'}{'symb'}; + my $slot_name = $log{$id}{'logentry'}{'slot'}; + my %slot=&Apache::lonnet::get_slot($slot_name); + my $description = $slot{'description'}; + my $start = ($slot{'starttime'}? + &Apache::lonlocal::locallocaltime($slot{'starttime'}):''); + my $end = ($slot{'endtime'}? + &Apache::lonlocal::locallocaltime($slot{'endtime'}):''); + my $title = &get_resource_title($symb,\%titles,\%maptitles); + my $chgaction = $log{$id}{'logentry'}{'action'}; + if ($chgaction ne '' && $lt{$chgaction} ne '') { + $chgaction = $lt{$chgaction}; + } + $r->print(&Apache::loncommon::start_data_table_row().''.$count.''.&Apache::lonlocal::locallocaltime($log{$id}{'exe_time'}).''.$chgaction.''.$description.''.$start.''.$end.''.$title.''.&Apache::loncommon::end_data_table_row()."\n"); + } + if ($showntablehdr) { + $r->print(&Apache::loncommon::end_data_table().'
'); + if (($curr{'page'} > 1) || ($more_records)) { + $r->print(''); + if ($curr{'page'} > 1) { + $r->print(''); + } + if ($more_records) { + $r->print(''); + } + $r->print('
'.&mt('Previous [_1] changes',$curr{'show'}).''.&mt('Next [_1] changes',$curr{'show'}).'
'); + $r->print(<<"ENDSCRIPT"); + +ENDSCRIPT + } + } else { + $r->print('' + .&mt('There are no transactions to display') + .'' + ); + } + $r->print(''."\n". + ''."\n"); + if ($env{'form.origin'} eq 'aboutme') { + $r->print(''."\n". + ''."\n". + ''."\n"); + } + $r->print('
'); + return; +} + +sub show_reservations_log { + my ($r) = @_; + my $badslot; + if ($env{'form.slotname'} eq '') { + $r->print('
'.&mt('No slot name provided').'
'); + $badslot = 1; + } else { + my %slot=&Apache::lonnet::get_slot($env{'form.slotname'}); + if (keys(%slot) == 0) { + $r->print('
'.&mt('Invalid slot name: [_1]',$env{'form.slotname'}).'
'); + $badslot = 1; + } elsif ($slot{type} ne 'schedulable_student') { + my $description = &get_description($env{'form.slotname'},\%slot); + $r->print('
'.&mt('Reservation history unavailable for non-student-reservable slot: [_1].',$description).'
'); + $badslot = 1; + } + } + if ($badslot) { + $r->print('

'. + &mt('Return to slot list').'

'); + return; + } + my $formname = 'reservationslog'; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my %slotlog=&Apache::lonnet::dump('nohist_slotreservationslog',$cdom,$cnum); + if ((keys(%slotlog))[0]=~/^error\:/) { undef(%slotlog); } + + my (%log,@allsymbs); + if (keys(%slotlog)) { + foreach my $key (keys(%slotlog)) { + if (ref($slotlog{$key}) eq 'HASH') { + if (ref($slotlog{$key}{'logentry'}) eq 'HASH') { + if ($slotlog{$key}{'logentry'}{'slot'} eq $env{'form.slotname'}) { + $log{$key} = $slotlog{$key}; + if ($slotlog{$key}{'logentry'}{'symb'} ne '') { + push(@allsymbs,$slotlog{$key}{'logentry'}{'symb'}); + } + } + } + } + } + } + + $r->print('
'); + my %saveable_parameters = ('show' => 'scalar',); + &Apache::loncommon::store_course_settings('reservationslog', + \%saveable_parameters); + &Apache::loncommon::restore_course_settings('reservationslog', + \%saveable_parameters); + # set defaults + my $now = time(); + my $defstart = $now - (7*24*3600); #7 days ago + my %defaults = ( + page => '1', + show => '10', + chgcontext => 'any', + action => 'any', + symb => 'any', + log_start_date => $defstart, + log_end_date => $now, + ); + my $more_records = 0; + + # set current + my %curr; + foreach my $item ('show','page','chgcontext','action','symb') { + $curr{$item} = $env{'form.'.$item}; + } + my ($startdate,$enddate) = + &Apache::lonuserutils::get_dates_from_form('log_start_date', + 'log_end_date'); + $curr{'log_start_date'} = $startdate; + $curr{'log_end_date'} = $enddate; + foreach my $key (keys(%defaults)) { + if ($curr{$key} eq '') { + $curr{$key} = $defaults{$key}; + } + } + my (%whodunit,%changed,$version); + ($version) = ($r->dir_config('lonVersion') =~ /^([\d\.]+)\-/); + + my %slot=&Apache::lonnet::get_slot($env{'form.slotname'}); + my $description = $slot{'description'}; + $r->print(''. + &mt('Reservation changes for student-reservable slot: [_1]',$description).'
'); + + $r->print(&display_filter($formname,$cdom,$cnum,\%curr,$version,\@allsymbs)); + my $showntablehdr = 0; + my $tablehdr = &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + ' '.&mt('When').''.&mt('Who made the change'). + ''.&mt('Affected User').''.&mt('Action').''. + ''.&mt('Resource').''.&mt('Context').''. + &Apache::loncommon::end_data_table_header_row(); + my ($minshown,$maxshown); + $minshown = 1; + my $count = 0; + if ($curr{'show'} ne &mt('all')) { + $maxshown = $curr{'page'} * $curr{'show'}; + if ($curr{'page'} > 1) { + $minshown = 1 + ($curr{'page'} - 1) * $curr{'show'}; + } + } + my %lt = &reservationlog_contexts(); + my (%titles,%maptitles); + foreach my $id (sort { $log{$b}{'exe_time'}<=>$log{$a}{'exe_time'} } (keys(%log))) { + next if (($log{$id}{'exe_time'} < $curr{'log_start_date'}) || + ($log{$id}{'exe_time'} > $curr{'log_end_date'})); + if ($curr{'show'} ne &mt('all')) { + if ($count >= $curr{'page'} * $curr{'show'}) { + $more_records = 1; + last; + } + } + if ($curr{'chgcontext'} ne 'any') { + if ($curr{'chgcontext'} eq 'user') { + next if (($log{$id}{'logentry'}{'context'} ne 'user') && + ($log{$id}{'logentry'}{'context'} ne 'usermanage')); + } else { + next if ($log{$id}{'logentry'}{'context'} ne $curr{'chgcontext'}); + } + } + if ($curr{'action'} ne 'any') { + next if ($log{$id}{'logentry'}{'action'} ne $curr{'action'}); + } + if ($curr{'symb'} ne 'any') { + next if ($log{$id}{'logentry'}{'symb'} ne $curr{'symb'}); + } + $count ++; + next if ($count < $minshown); + if (!$showntablehdr) { + $r->print($tablehdr); + $showntablehdr = 1; + } + if ($whodunit{$log{$id}{'exe_uname'}.':'.$log{$id}{'exe_udom'}} eq '') { + $whodunit{$log{$id}{'exe_uname'}.':'.$log{$id}{'exe_udom'}} = + &Apache::loncommon::plainname($log{$id}{'exe_uname'},$log{$id}{'exe_udom'}); + } + if ($changed{$log{$id}{'uname'}.':'.$log{$id}{'udom'}} eq '') { + $changed{$log{$id}{'uname'}.':'.$log{$id}{'udom'}} = + &Apache::loncommon::plainname($log{$id}{'uname'},$log{$id}{'udom'}); + } + my $symb = $log{$id}{'logentry'}{'symb'}; + my $title = &get_resource_title($symb,\%titles,\%maptitles); + my $chgcontext = $log{$id}{'logentry'}{'context'}; + if ($chgcontext ne '' && $lt{$chgcontext} ne '') { + $chgcontext = $lt{$chgcontext}; + } + my $chgaction = $log{$id}{'logentry'}{'action'}; + if ($chgaction ne '' && $lt{$chgaction} ne '') { + $chgaction = $lt{$chgaction}; + } + $r->print(&Apache::loncommon::start_data_table_row().''.$count.''.&Apache::lonlocal::locallocaltime($log{$id}{'exe_time'}).''.$whodunit{$log{$id}{'exe_uname'}.':'.$log{$id}{'exe_udom'}}.''.$changed{$log{$id}{'uname'}.':'.$log{$id}{'udom'}}.''.$chgaction.''.$title.''.$chgcontext.''.&Apache::loncommon::end_data_table_row()."\n"); + } + if ($showntablehdr) { + $r->print(&Apache::loncommon::end_data_table().'
'); + if (($curr{'page'} > 1) || ($more_records)) { + $r->print(''); + if ($curr{'page'} > 1) { + $r->print(''); + } + if ($more_records) { + $r->print(''); + } + $r->print('
'.&mt('Previous [_1] changes',$curr{'show'}).''.&mt('Next [_1] changes',$curr{'show'}).'
'); + $r->print(<<"ENDSCRIPT"); + +ENDSCRIPT + } + } else { + $r->print(&mt('There are no records to display')); + } + $r->print(''. + ''. + '
'. + '

'. + &mt('Return to slot list').'

'); + return; +} + +sub get_resource_title { + my ($symb,$titles,$maptitles) = @_; + my $title; + if ((ref($titles) eq 'HASH') && (ref($maptitles) eq 'HASH')) { + if (defined($titles->{$symb})) { + $title = $titles->{$symb}; + } else { + $title = &Apache::lonnet::gettitle($symb); + my $maptitle; + my ($mapurl) = &Apache::lonnet::decode_symb($symb); + if (defined($maptitles->{$mapurl})) { + $maptitle = $maptitles->{$mapurl}; + } else { + if ($mapurl eq $env{'course.'.$env{'request.course.id'}.'.url'}) { + $maptitle=&mt('Main Course Documents'); + } else { + $maptitle=&Apache::lonnet::gettitle($mapurl); + } + $maptitles->{$mapurl} = $maptitle; + } + if ($maptitle ne '') { + $title .= ' '.&mt('(in [_1])',$maptitle); + } + $titles->{$symb} = $title; + } + } else { + $title = $symb; + } + return $title; +} + +sub reservationlog_contexts { + my %lt = &Apache::lonlocal::texthash ( + any => 'Any', + user => 'By student', + manage => 'Via Slot Manager', + parameter => 'Via Parameter Manager', + reserve => 'Made reservation', + release => 'Dropped reservation', + usermanage => 'By student', + ); + return %lt; +} + +sub display_filter { + my ($formname,$cdom,$cnum,$curr,$version,$allsymbs) = @_; + my $nolink = 1; + my (%titles,%maptitles); + my $output = '
'; + my $startform = + &Apache::lonhtmlcommon::date_setter($formname,'log_start_date', + $curr->{'log_start_date'},undef, + undef,undef,undef,undef,undef,undef,$nolink); + my $endform = + &Apache::lonhtmlcommon::date_setter($formname,'log_end_date', + $curr->{'log_end_date'},undef, + undef,undef,undef,undef,undef,undef,$nolink); + my %lt = &reservationlog_contexts(); + $output .= ''; + if (ref($allsymbs) eq 'ARRAY') { + $output .= ''; + } else { + $output .= ''; + } + $output .= '
'. + ''.&mt('Changes/page:').'
'. + &Apache::lonmeta::selectbox('show',$curr->{'show'},undef, + (&mt('all'),5,10,20,50,100,1000,10000)). + '
  '.&mt('Window during which changes occurred:'). + '
'.&mt('After:'). + ''.$startform.'
'.&mt('Before:').''. + $endform.'
  '.&mt('Resource').'
'. + '
  '. + &mt('Context:').'
'.&mt('Action').'
'. + '
  
'. + ''. + &mt('[_1]Note:[_2] Only changes made from servers running LON-CAPA 2.8.99.0 or later are displayed.'); + if ($version) { + $output .= ' '.&mt('This server is version [_3].','','',$version); + } + $output .= '

'; + return $output; } sub upload_start { my ($r)=@_; $r->print(&Apache::grades::checkforfile_js()); - my $result.='
'."\n"; + my $result.=''."\n"; @@ -1387,7 +2103,7 @@ Total number of records found in file: $ Enter as many fields as you can. The system will inform you and bring you back to this page if the data selected is insufficient to create the slots.
- + @@ -1623,6 +2339,23 @@ sub csv_upload_assign { return ''; } +sub slot_command_titles { + my %titles = ( + slotlog => 'Reservation Logs', + showslots => 'Manage Slots', + showresv => 'Reservation History', + manageresv => 'Manage Reservations', + uploadstart => 'Upload Slots File', + csvuploadmap => 'Upload Slots File', + csvuploadassign => 'Upload Slots File', + delete => 'Slot Deletion', + release => 'Reservation Result', + remove_reservation => 'Remove Registration', + get_reservation => 'Request Reservation', + ); + return %titles; +} + sub handler { my $r=shift; @@ -1634,16 +2367,65 @@ sub handler { } &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); - + + my %crumb_titles = &slot_command_titles(); + my $brcrum; + my $vgr=&Apache::lonnet::allowed('vgr',$env{'request.course.id'}); my $mgr=&Apache::lonnet::allowed('mgr',$env{'request.course.id'}); + if ($env{'form.command'} eq 'showslots') { + if (($vgr ne 'F') && ($mgr ne 'F')) { + $env{'form.command'} = 'manageresv'; + } + } elsif ($env{'form.command'} eq 'manageresv') { + if (($vgr eq 'F') || ($mgr eq 'F')) { + $env{'form.command'} = 'showslots'; + } + } my $title='Requesting Another Worktime'; - if ($env{'form.command'} =~ /^(showslots|uploadstart|csvuploadmap|csvuploadassign)$/ && $vgr eq 'F') { - $title = 'Managing Slots'; + if ($env{'form.command'} eq 'showresv') { + $title = 'Reservation History'; + if ($env{'form.origin'} eq 'aboutme') { + $brcrum =[{href=>"/adm/$env{'form.udom'}/$env{'form.uname'}/aboutme",text=>'Personal Information Page'}]; + } else { + $brcrum =[{href=>"/adm/slotrequest?command=manageresv",text=>'Manage Reservations'}]; + } + 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 ($vgr eq 'F') { + if ($env{'form.command'} =~ /^(slotlog|showslots|uploadstart|csvuploadmap|csvuploadassign|delete|release|remove_registration)$/) { + $brcrum =[{href=>"/adm/slotrequest?command=showslots", + text=>$crumb_titles{'showslots'}}]; + $title = 'Managing Slots'; + unless ($env{'form.command'} eq 'showslots') { + if (ref($brcrum) eq 'ARRAY') { + push(@{$brcrum},{href=>"/adm/slotrequest?command=$env{'form.command'}",text=>$crumb_titles{$env{'form.command'}}}); + } + } + } + } elsif ($env{'form.command'} eq 'release') { + if ($env{'form.context'} eq 'usermanage') { + $brcrum =[{href=>"/adm/slotrequest?command=manageresv", + text=>$crumb_titles{'showslots'}}]; + $title = 'Manage Reservations'; + if (ref($brcrum) eq 'ARRAY') { + push(@{$brcrum},{href=>"/adm/slotrequest?command=$env{'form.command'}",text=>$crumb_titles{$env{'form.command'}}}); + } + + } } - &start_page($r,$title); + &start_page($r,$title,$brcrum); - if ($env{'form.command'} eq 'showslots' && $vgr eq 'F') { + if ($env{'form.command'} eq 'manageresv') { + my $crstype = &Apache::loncommon::course_type(); + &manage_reservations($r,$crstype); + } elsif ($env{'form.command'} eq 'showresv') { + &show_reservations($r,$env{'form.uname'},$env{'form.udom'}); + } elsif ($env{'form.command'} eq 'showslots' && $vgr eq 'F') { &show_table($r,$mgr); } elsif ($env{'form.command'} eq 'remove_registration' && $mgr eq 'F') { &remove_registration($r); @@ -1670,6 +2452,8 @@ sub handler { } &csv_upload_map($r); } + } elsif ($env{'form.command'} eq 'slotlog' && $mgr eq 'F') { + &show_reservations_log($r); } else { my $symb=&unescape($env{'form.symb'}); if (!defined($symb)) { 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.

'."\n"; $result.=' '. &mt('Specify a file containing the slot definitions.'). '