--- loncom/interface/slotrequest.pm 2007/04/10 23:28:20 1.75
+++ loncom/interface/slotrequest.pm 2023/07/12 15:48:23 1.147
@@ -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.75 2007/04/10 23:28:20 albertel Exp $
+# $Id: slotrequest.pm,v 1.147 2023/07/12 15:48:23 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)=@_;
@@ -50,14 +50,56 @@ sub fail {
} else {
$r->print('
'.&mt('Failed.').'
');
}
-
+
&return_link($r);
&end_page($r);
}
sub start_page {
- my ($r,$title)=@_;
- $r->print(&Apache::loncommon::start_page($title));
+ my ($r,$title,$brcrum,$bread_crumbs_component,$js,$mgr)=@_;
+ my $args;
+ if (ref($brcrum) eq 'ARRAY') {
+ $args = {bread_crumbs => $brcrum};
+ if ($bread_crumbs_component) {
+ $args->{bread_crumbs_component} = $bread_crumbs_component;
+ }
+ }
+ 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 };
+ }
+ }
+ unless (($env{'form.context'} eq 'usermanage') || (($mgr eq 'F') &&
+ (($env{'form.command'} eq 'release') ||
+ ($env{'form.command'} eq 'remove_registration')))) {
+ if ($env{'form.symb'}) {
+ my $symb=&unescape($env{'form.symb'});
+ my ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($symb);
+ if ($resurl =~ /ext\.tool$/) {
+ my $target;
+ my ($marker,$exttool) = (split(m{/},$resurl))[3,4];
+ $marker=~s/\D//g;
+ if (($marker) && ($exttool) && ($env{'request.course.id'})) {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my ($idx,$crstool,$is_tool,%toolhash,%toolsettings);
+ if ($resurl eq "adm/$cdom/$cnum/$marker/$exttool") {
+ my %toolsettings=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum);
+ $target = $toolsettings{'target'};
+ }
+ }
+ if ($target eq 'iframe') {
+ $args->{'only_body'} = 1;
+ }
+ }
+ }
+ }
+ $r->print(&Apache::loncommon::start_page($title,$js,$args));
}
sub end_page {
@@ -65,6 +107,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
@@ -85,7 +412,7 @@ sub get_course {
sub get_reservation_ids {
my ($slot_name)=@_;
-
+
my ($cnum,$cdom)=&get_course();
my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
@@ -117,7 +444,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));
@@ -131,24 +457,22 @@ sub check_for_reservation {
|| &Apache::lonnet::error($course)
|| &Apache::lonnet::error(%slots)) {
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,'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 {
@@ -165,8 +489,11 @@ sub check_for_reservation {
sub get_consumed_uniqueperiods {
my ($slots) = @_;
my $navmap=Apache::lonnavmaps::navmap->new;
+ if (!defined($navmap)) {
+ 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();
@@ -213,12 +540,19 @@ sub check_for_conflict {
if (!defined($new_slot->{'uniqueperiod'})) { return undef; }
if (!ref($consumed_uniqueperiods)) {
- $consumed_uniqueperiods = &get_consumed_uniqueperiods($slots);
- if (&Apache::lonnet::error(%$consumed_uniqueperiods)) {
- return 'error: Unable to determine current status';
- }
- }
-
+ if ($consumed_uniqueperiods =~ /^error: /) {
+ return $consumed_uniqueperiods;
+ } else {
+ $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}};
@@ -229,19 +563,17 @@ sub check_for_conflict {
}
}
return undef;
-
}
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'});
&Apache::lonxml::debug("value is $value ");
- my $use_slots = &Apache::lonnet::EXT("resource.0.useslots");
+ my $use_slots = &Apache::lonnet::EXT("resource.0.useslots",$symb,
+ $env{'user.domain'},$env{'user.name'});
&Apache::lonxml::debug("use_slots is $use_slots ");
if (&Apache::lonnet::error($value)
@@ -249,18 +581,18 @@ sub make_reservation {
return 'error: Unable to determine current status';
}
- my $parm_symb = $symb;
+ my $symb_for_db = $symb;
my $parm_level = 1;
if ($use_slots eq 'map' || $use_slots eq 'map_map') {
my ($map) = &Apache::lonnet::decode_symb($symb);
- $parm_symb = &Apache::lonnet::symbread($map);
+ $symb_for_db = &Apache::lonnet::symbread($map);
$parm_level = 2;
}
foreach my $other_slot (split(/:/, $value)) {
if ($other_slot eq $slot_name) {
my %consumed=&Apache::lonnet::dump('slot_reservations', $cdom,
- $cnum, "^$slot_name\0");
+ $cnum, "^$slot_name\0");
if (&Apache::lonnet::error($value)) {
return 'error: Unable to determine current status';
}
@@ -286,17 +618,17 @@ sub make_reservation {
my $num=(split('\0',$id))[1];
if ($num > $last) { $last=$num; }
}
-
+
my $wanted=$last+1;
&Apache::lonxml::debug("wanted $wanted ");
if (scalar(@ids) >= $max) {
# full up
return undef;
}
-
+
my %reservation=('name' => $env{'user.name'}.':'.$env{'user.domain'},
'timestamp' => time,
- 'symb' => $parm_symb);
+ 'symb' => $symb_for_db);
my $success=&Apache::lonnet::newput('slot_reservations',
{"$slot_name\0$wanted" =>
@@ -308,13 +640,9 @@ 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");
+ my $result = &store_slot_parm($symb,$symb_for_db,$slot_name,$parm_level,
+ $new_value,$cnum,$cdom,$env{'user.name'},
+ $env{'user.domain'},'reserve',$env{'form.context'});
return $wanted;
}
@@ -322,6 +650,30 @@ sub make_reservation {
return undef;
}
+sub store_slot_parm {
+ my ($symb_for_parm,$symb_for_db,$slot_name,$parm_level,$new_value,
+ $cnum,$cdom,$uname,$udom,$action,$context,$delflag) = @_;
+
+ # store new parameter string
+ my $result=&Apache::lonparmset::storeparm_by_symb($symb_for_parm,
+ '0_availablestudent',
+ $parm_level,$new_value,
+ 'string',$uname,$udom);
+ &Apache::lonxml::debug("hrrm $result");
+ my %storehash = (
+ symb => $symb_for_db,
+ slot => $slot_name,
+ action => $action,
+ context => $context,
+ );
+
+ &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
+ $delflag,$uname,$udom,$cnum,$cdom);
+ &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
+ $delflag,$uname,$udom,$uname,$udom);
+ return $result;
+}
+
sub remove_registration {
my ($r) = @_;
if ($env{'form.entry'} ne 'remove all') {
@@ -334,12 +686,12 @@ sub remove_registration {
my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
"^$slot_name\0");
if (&Apache::lonnet::error(%consumed)) {
- $r->print("".&mt('A network error has occured.').'
');
+ $r->print("".&mt('A network error has occurred.').'
');
return;
}
if (!%consumed) {
- $r->print("".&mt('Slot [_1] has no reservations.',
- $slot_name)."
");
+ $r->print(''.&mt('Slot [_1] has no reservations.',
+ ''.$slot_name.' ').'
');
return;
}
@@ -347,12 +699,12 @@ 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 {
my ($r) = @_;
-
+
my $slot_name = $env{'form.slotname'};
my $name = &Apache::loncommon::plainname($env{'form.uname'},
@@ -362,9 +714,9 @@ sub remove_registration_user {
my $msg = &mt('Remove [_1] from slot [_2] for [_3]',
$name,$slot_name,$title);
-
+
&remove_registration_confirmation($r,$msg,['uname','udom','slotname',
- 'entry','symb']);
+ 'entry','symb','context']);
}
sub remove_registration_confirmation {
@@ -376,8 +728,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
-
-or
STUFF
- if (!$inhibit_return_link) { &return_link($r); }
+ if (!$inhibit_return_link) {
+ $r->print(&mt('or').'');
+ &return_link($r);
+ } else {
+ $r->print('');
+ }
return 0;
}
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) {
- # all open slot to be schedulable
- #return 0;
+ return 0;
}
&Apache::lonxml::debug("$slot_name starttime good");
@@ -668,6 +1336,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;
@@ -712,14 +1385,40 @@ 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,
$consumed_uniqueperiods);
- if ($conflict) {
+ if ($conflict =~ /^error: /) {
+ return 0;
+ } elsif ($conflict ne '') {
if ($slots->{$conflict}{'starttime'} < time) {
return 0;
}
@@ -740,67 +1439,176 @@ sub get_description {
}
sub show_choices {
- my ($r,$symb)=@_;
-
- my ($cnum,$cdom)=&get_course();
- my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum);
- my $consumed_uniqueperiods = &get_consumed_uniqueperiods(\%slots);
- my $available;
- $r->print('');
+ 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');
- 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},undef,\%slots,
- $consumed_uniqueperiods));
-
- $available++;
-
- my $description=&get_description($slot,$slots{$slot});
+ if (!ref($available) eq 'ARRAY') {
+ return;
+ }
+ if (!@{$available}) {
+ $output = ''.&mt('No available times.').' ';
+ if ($env{'form.command'} ne 'manageresv') {
+ my $target = &return_target();
+ $output .= ' '.
+ &mt('Return to last resource').' ';
+ }
+ 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 .= ''.
+ ' '.
+ $resmenu{$option}.
+ ' '.(' ' 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";
+
+
- my $form=&mt('Unavailable');
- if ((grep(/^\Q$slot\E$/,@got_slots)) ||
- &space_available($slot,$slots{$slot},$symb)) {
+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 ($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;
+ if ((grep(/^\Q$slot\E$/,@{$got_slots})) ||
+ &space_available($slot,$slots->{$slot},$symb)) {
my $text=&mt('Select');
my $command='get';
- if (grep(/^\Q$slot\E$/,@got_slots)) {
+ if (grep(/^\Q$slot\E$/,@{$got_slots})) {
$text=&mt('Drop Reservation');
$command='release';
} else {
- my $conflict = &check_for_conflict($symb,$slot,$slots{$slot},
- \%slots,
- $consumed_uniqueperiods);
- if ($conflict) {
- $text=&mt('Change Reservation');
- $command='get';
- }
+ my $conflict = &check_for_conflict($symb,$slot,$slots->{$slot},
+ $slots,$consumed_uniqueperiods);
+ if ($conflict) {
+ if ($conflict =~ /^error: /) {
+ $form = ''.
+ &mt('Slot: [_1] has unknown status.',$description).
+ ' ';
+ } else {
+ $text=&mt('Change Reservation');
+ $command='get';
+ }
+ }
}
my $escsymb=&escape($symb);
- $form=<
+ if (!$form) {
+ my $name;
+ if ($formname) {
+ $name = '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('','LC_slotrow_'.$num.'_'.$slot);
+ }
+ $output .= "
$form
- $description
-
-STUFF
+ $description \n";
+ if ($env{'form.command'} eq 'manageresv') {
+ $output .= '';
+ } else {
+ $output .= &Apache::loncommon::end_data_table_row();
+ }
}
-
- if (!$available) {
- $r->print('No available times. '.
- &mt('Return to last resource').' ');
+ if ($env{'form.command'} eq 'manageresv') {
+ $output .= '
';
+ } else {
+ $output .= &Apache::loncommon::end_data_table();
+ }
+ if (@{$available} > 1) {
+ $output .= '
';
+ }
+ if ($class) {
+ return ''.$output.'
';
+ } else {
+ return $output;
}
- $r->print('
');
}
sub to_show {
@@ -862,7 +1670,7 @@ sub to_show {
}
return 0;
}
-
+
return 1;
}
@@ -884,7 +1692,7 @@ sub remove_link {
$symb = &escape($symb);
return <<"END_LINK";
- ($remove)
END_LINK
@@ -894,15 +1702,13 @@ sub show_table {
my ($r,$mgr)=@_;
my ($cnum,$cdom)=&get_course();
+ my $crstype=&Apache::loncommon::course_type($cdom.'_'.$cnum);
my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum);
if ( (keys(%slots))[0] =~ /^error: 2 /) {
undef(%slots);
}
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('');
$r->print('
@@ -912,10 +1718,19 @@ sub show_table {
$r->print('
');
- $r->print(&Apache::loncommon::help_open_topic('Slot AddInterface'));
+ $r->print(&Apache::loncommon::help_open_topic('Slot About'));
$r->print('');
}
-
+
+ if (!keys(%slots)) {
+ $r->print(
+ ''
+ .&mt('No slots have been created in this '.lc($crstype).'.')
+ .'
'
+ );
+ return;
+ }
+
my %Saveable_Parameters = ('show' => 'array',
'when' => 'scalar',
'order' => 'scalar',
@@ -939,18 +1754,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')
@@ -997,7 +1820,7 @@ sub show_table {
my $name_filter = {'type' => $name_filter_type,
'value' => $env{'form.name_filter_value'},};
-
+
#deleted slot filtering
#default to hide if no value
$env{'form.deleted'} ||= 'hide';
@@ -1016,31 +1839,31 @@ 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).
+ \%name_filter_type_fields).
' '.
&Apache::lonhtmlcommon::textbox('name_filter_value',
$env{'form.name_filter_value'},
15).
'
-
+
- Deleted slots:
- '.$show_radio.'Show
+ '.&mt('Deleted slots:').'
+ '.$show_radio.&mt('Show').'
- '.$hide_radio.'Hide
+ '.$hide_radio.&mt('Hide').'
@@ -1049,19 +1872,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'}})
@@ -1076,7 +1900,7 @@ sub show_table {
return lc($a) cmp lc($b);
}
} elsif ($env{'form.order'} eq 'uniqueperiod') {
-
+
if ($slots{$a}->{'uniqueperiod'}[0]
ne $slots{$b}->{'uniqueperiod'}[0]) {
return ($slots{$a}->{'uniqueperiod'}[0]
@@ -1098,26 +1922,30 @@ 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);
-
+
if (exists($show{'scheduled'}) || exists($show{'space'}) ) {
- my @this_slot = grep(/^$slot\0/,keys(%consumed));
+ my $re_str = "$slot\0";
+ my @this_slot = grep(/^\Q$re_str\E/,keys(%consumed));
$id_count = scalar(@this_slot);
if (exists($show{'scheduled'})) {
foreach my $entry (sort { $consumed{$a}{name} cmp
$consumed{$b}{name} }
- (keys(%consumed))) {
+ (@this_slot)) {
my (undef,$id)=split("\0",$entry);
my ($uname,$udom) = split(':',$consumed{$entry}{'name'});
- $ids.= '';
+ $ids.= '';
foreach my $item (@stu_display_order) {
if ($stu_display{$item}) {
if ($item eq 'fullname') {
@@ -1128,7 +1956,7 @@ sub show_table {
}
}
$ids.=&remove_link($slot,$entry,$uname,$udom,
- $consumed{$entry}{'symb'}).' ';
+ $consumed{$entry}{'symb'}).' ';
}
}
}
@@ -1139,6 +1967,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'})) {
@@ -1146,13 +1976,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;
@@ -1195,26 +2033,48 @@ sub show_table {
}
my $proctors=join(', ',@proctors);
- my $edit=(<<"EDITLINK");
-Edit
+ my %lt = &Apache::lonlocal::texthash (
+ edit => 'Edit',
+ delete => 'Delete',
+ slotlog => 'History',
+ );
+ my ($edit,$delete,$showlog,$remove_all);
+ if ($mgr) {
+ $edit=(<<"EDITLINK");
+$lt{'edit'}
EDITLINK
- my $delete=(<<"DELETELINK");
-Delete
+ $delete=(<<"DELETELINK");
+$lt{'delete'}
DELETELINK
- my $remove_all=&remove_link($slot,'remove all').' ';
+ $remove_all=&remove_link($slot,'remove all').' ';
+
+ if ($ids eq '') {
+ undef($remove_all);
+ } else {
+ undef($delete);
+ }
+ }
+
+ $showlog=(<<"LOGLINK");
+$lt{'slotlog'}
+LOGLINK
- if ($ids ne '') { undef($delete); }
- if ($slots{$slot}{'type'} ne 'schedulable_student'
- || $ids eq '') {
+ 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.
- "\n$edit $delete \n");
+ "\n$edit $delete $showlog \n");
if (exists($show{'name'})) {
$colspan++;$r->print("$slot ");
}
@@ -1233,6 +2093,12 @@ DELETELINK
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");
}
@@ -1249,8 +2115,18 @@ DELETELINK
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");
@@ -1273,30 +2149,905 @@ $row_end
STUFF
}
}
- $r->print('');
+ 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,$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.')
+ .' '
+ .&mt('One example is for management of laboratory space, which is only available at certain times, and has a limited number of seats.')
+ .'
'
+ );
+ if (!defined($navmap)) {
+ $r->print('');
+ if ($crstype eq 'Community') {
+ $r->print(&mt('Unable to retrieve information about community contents'));
+ } else {
+ $r->print(&mt('Unable to retrieve information about course contents'));
+ }
+ $r->print('
');
+ &Apache::lonnet::logthis('Manage Reservations - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
+ return;
+ }
+ 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";
+ 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} = $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';
+ }
+ if ($shownmaps{$currmap}) {
+ $mapnum ++;
+ $rownum ++;
+ $shown ++;
+ 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';
+ }
+ $row .= ''.$spacers.' '.
+ $icon.(' ' x6).' '."\n";
+ if (ref($output{$currmap}) eq 'HASH') {
+ my $formnum = $mapnum.'_'.$reservable+1;
+ my $class = 'LC_slotmaptext_'.$mapnum;
+ if ($output{$currmap}{'hasaction'}) {
+ $row .= ''.
+ $output{$currmap}{'msg'}.
+ ' '.
+ &slot_chooser($repsymbs{$currmap},$class,$formnum,
+ $allavailable,$slots,$consumed_uniqueperiods).
+ ' ';
+ } else {
+ $row .= ''.
+ $output{$currmap}{'msg'}.
+ ' ';
+ }
+ $row .= ' '."\n";
+ } else {
+ $row .= ' '."\n";
+ }
+ } else {
+ my ($spacers,$icon) = &show_map_row($depth,$location,$currmaptype,$currmaptitle);
+ $row .= ''.$spacers.$icon.(' ' x6).' '."\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 ++;
+ if (!$shownheader) {
+ $r->print($slotheader);
+ $shownheader = 1;
+ }
+ 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(' ');
+ }
+ $r->print(''.
+ ''.$title.' '.(' ' x6).' ');
+ my $class = 'LC_slottext_'.$mapnum;
+ if ($output{$symb}{'hasaction'}) {
+ $r->print(''.$output{$symb}{'msg'}.' '.
+ ''.
+ &slot_chooser($symb,$class,$reservable,$allavailable,$slots,
+ $consumed_uniqueperiods).' ');
+ } else {
+ $r->print(''.
+ ''.$output{$symb}{'msg'}.' '.
+ ' ');
+ }
+ $r->print(' '."\n");
+ }
+ }
+ }
+ if ($shownheader) {
+ $r->print('
');
+ }
+ if (!$reservable) {
+ $r->print('');
+ if ($crstype eq 'Community') {
+ $r->print(&mt('No community items currently require a reservation to gain access.'));
+ } else {
+ $r->print(&mt('No course items currently require a reservation to gain access.'));
+ }
+ $r->print(' ');
+ }
+ $r->print(''.
+ &mt('Reservation History').'
');
+}
+
+sub show_map_row {
+ my ($depth,$location,$type,$title) = @_;
+ my $spacers;
+ for (my $i=0; $i<$depth-1; $i++) {
+ $spacers .= ' ';
+ }
+ my $icon;
+ if ($type eq 'page') {
+ $icon = ' '."\n";
+ } else {
+ $icon = ' '."\n";
+ }
+ $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 {
+ my ($r,$uname,$udom) = @_;
+ if (!defined($uname)) {
+ $uname = $env{'user.name'};
+ }
+ if (!defined($udom)) {
+ $udom = $env{'user.domain'};
+ }
+ my $formname = 'slotlog';
+ 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') {
+ $r->print('');
+ my $name = &Apache::loncommon::plainname($env{'form.uname'},$env{'form.udom'},
+ 'firstname');
+ if ($crstype eq 'Community') {
+ $r->print(&mt('History of member-reservable slots for: [_1]',
+ $name));
+ } else {
+ $r->print(&mt('History of student-reservable slots for: [_1]',
+ $name));
+
+ }
+ $r->print('
');
+ }
+ $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($crstype);
+ 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('
');
+ $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;
+ my $crstype = &Apache::loncommon::course_type();
+ 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('');
+ if ($crstype eq 'Community') {
+ $r->print(&mt('Reservation history unavailable for non-member-reservable slot: [_1].',$description));
+ } else {
+ $r->print(&mt('Reservation history unavailable for non-student-reservable slot: [_1].',$description));
+ }
+ $r->print('
');
+ $badslot = 1;
+ }
+ }
+ if ($badslot) {
+ $r->print(''.
+ &mt('Return to slot list').'
');
+ return;
+ }
+ my $formname = 'reservationslog';
+ my ($cnum,$cdom)=&get_course();
+ 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('');
+ if ($crstype eq 'Community') {
+ $r->print(&mt('Reservation changes for member-reservable slot: [_1]',$description));
+ } else {
+ $r->print(&mt('Reservation changes for student-reservable slot: [_1]',$description));
+ }
+ $r->print(' ');
+ $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($crstype);
+ 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('
');
+ $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 Content');
+ } 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 ($crstype) = @_;
+ 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',
+ );
+ if ($crstype eq 'Community') {
+ $lt{'user'} = &mt('By member');
+ $lt{'usermanage'} = $lt{'user'};
+ }
+ return %lt;
+}
+
+sub display_filter {
+ my ($formname,$cdom,$cnum,$curr,$version,$allsymbs) = @_;
+ my $nolink = 1;
+ my (%titles,%maptitles);
+ my $output = ''.
+ ''.&mt('Changes/page:').' '.
+ &Apache::lonmeta::selectbox('show',$curr->{'show'},'',undef,
+ (&mt('all'),5,10,20,50,100,1000,10000)).
+ ' ';
+ 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 $crstype = &Apache::loncommon::course_type();
+ my %lt = &reservationlog_contexts($crstype);
+ $output .= ''.&mt('Window during which changes occurred:').
+ ' '.&mt('After:').
+ ' '.$startform.' '.&mt('Before:').' '.
+ $endform.'
';
+ if (ref($allsymbs) eq 'ARRAY') {
+ $output .= ''.&mt('Resource').' '.
+ '{'resource'} eq 'any') {
+ $output .= ' selected="selected"';
+ }
+ $output .= '>'.&mt('Any').' '."\n";
+ foreach my $symb (@{$allsymbs}) {
+ my $title = &get_resource_title($symb,\%titles,\%maptitles);
+ my $selstr = '';
+ if ($curr->{'resource'} eq $symb) {
+ $selstr = ' selected="selected"';
+ }
+ $output .= ' '.$title.' ';
+ }
+ $output .= ' '.
+ &mt('Context:').' ';
+ foreach my $chgtype ('any','user','manage','parameter') {
+ my $selstr = '';
+ if ($curr->{'chgcontext'} eq $chgtype) {
+ $output .= $selstr = ' selected="selected"';
+ }
+ $output .= ''.$lt{$chgtype}.' '."\n";
+ }
+ $output .= ' ';
+ } else {
+ $output .= ''.&mt('Action').' '.
+ '{'action'} eq 'any') {
+ $output .= ' selected="selected"';
+ }
+ $output .= '>'.&mt('Any').' '."\n";
+ foreach my $actiontype ('reserve','release') {
+ my $selstr = '';
+ if ($curr->{'action'} eq $actiontype) {
+ $output .= $selstr = ' selected="selected"';
+ }
+ $output .= ''.$lt{$actiontype}.' '."\n";
+ }
+ $output .= ' ';
+ }
+ $output .= '
'.
+ '
'.
+ ''.
+ &mt('Only changes made from servers running LON-CAPA [_1] or later are displayed.'
+ ,'2.9.0');
+ if ($version) {
+ $output .= ' '.&mt('This LON-CAPA server is version [_1]',$version);
+ }
+ $output .= '
';
+ return $output;
+}
+
+sub slot_change_messaging {
+ my ($setting,$subject,$msg,$action) = @_;
+ my $user = $env{'user.name'};
+ my $domain = $env{'user.domain'};
+ my ($message_status,$comment_status);
+ if ($setting eq 'only_student'
+ || $setting eq 'student_and_user_notes_screen') {
+ $message_status =
+ &Apache::lonmsg::user_normal_msg($user,$domain,$subject,$msg);
+ $message_status = ''.&mt('Sent to you: [_1]',
+ $message_status).' ';
+ }
+ if ($setting eq 'student_and_user_notes_screen') {
+ $comment_status =
+ &Apache::lonmsg::store_instructor_comment($subject.' '.
+ $msg,$user,$domain);
+ $comment_status = ''.&mt('Entry added to course record (viewable by instructor): [_1]',
+ $comment_status).' ';
+ }
+ if ($message_status || $comment_status) {
+ my $msgtitle;
+ if ($action eq 'reserve') {
+ $msgtitle = &mt('Status of messages about saved reservation');
+ } elsif ($action eq 'release') {
+ $msgtitle = &mt('Status of messages about dropped reservation');
+ } elsif ($action eq 'nochange') {
+ $msgtitle = &mt('Status of messages about unchanged existing reservation');
+ }
+ return ''.$msgtitle.' '
+ .''
+ .$message_status
+ .$comment_status
+ .' ';
+ }
}
sub upload_start {
- my ($r)=@_;
- $r->print(&Apache::grades::checkforfile_js());
- my $result.=''."\n";
- $result.=' '."\n";
- $r->print($result);
+ my ($r)=@_;
+ $r->print(
+ &Apache::grades::checkforfile_js()
+ .''.&mt('Upload a file containing the slot definitions').' '
+ .''
+ .' '
+ .&Apache::lonhtmlcommon::start_pick_box()
+ .&Apache::lonhtmlcommon::row_title(&mt('File'))
+ .&Apache::loncommon::upfile_select_html()
+ .&Apache::lonhtmlcommon::row_closure()
+ .&Apache::lonhtmlcommon::row_title(
+ ''
+ .&mt('Ignore First Line')
+ .' ')
+ .' '
+ .&Apache::lonhtmlcommon::row_closure(1)
+ .&Apache::lonhtmlcommon::end_pick_box()
+ .''
+ .' '
+ .'
'
+ .' '
+ );
}
sub csvuploadmap_header {
@@ -1310,16 +3061,40 @@ sub csvuploadmap_header {
my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');
my $ignore=&mt('Ignore First Line');
- my $help_field = &Apache::loncommon::help_open_topic('Slot SelectingField');
+ my $buttontext = &mt('Reverse Association');
+
+ $r->print(
+ ''
+ .''.&mt('Identify fields in uploaded list').' '
+ .''
+ .&Apache::loncommon::help_open_topic(
+ 'Slot About',&mt('Help on slots'))
+ .' '.&Apache::loncommon::help_open_topic(
+ 'Slot SelectingField',&mt('Help on selecting Fields'))
+ ."
\n"
+ .''
+ .&mt('Total number of records found in file: [_1]',''.$distotal.' ')
+ ."
\n"
+ );
+ if ($distotal == 0) {
+ $r->print(''.&mt('None found').'
');
+ }
+ $r->print(
+ ''
+ .&mt('Enter as many fields as you can.').' '
+ .&mt('The system will inform you and bring you back to this page,[_1]if the data selected is insufficient to create the slots.',' ')
+ .'
'
+ );
+ $r->print(
+ ''
+ .'
'.&mt('Functions').' '
+ .' '.$ignore.' '
+ .' '
+ .' '
+ );
$r->print(<
-Identify fields $help_field
-Total number of records found in file: $distotal
-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.
-
- $ignore
@@ -1327,9 +3102,10 @@ to this page if the data selected is ins
-
ENDPICK
return '';
@@ -1338,17 +3114,17 @@ ENDPICK
sub csvuploadmap_footer {
my ($request,$i,$keyfields) =@_;
+ my $buttontext = &mt('Create Slots');
$request->print(<
-
+
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(<print('Creating Slots ');
+ $r->print(''.&mt('Creating Slots').' ');
my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};
my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
my $countdone=0;
@@ -1513,8 +3297,12 @@ sub csv_upload_assign {
}
if ($entries{$fields{'startreserve'}}) {
- $slot{'startreserve'}=
- &UnixDate($entries{$fields{'startreserve'}},"%s");
+ my $date = &UnixDate($entries{$fields{'startreserve'}},"%s");
+ if ($date eq '') {
+ push(@errors,"$name -- No reservation start time set for slot -- value provided had invalid format");
+ } else {
+ $slot{'startreserve'} = $date;
+ }
}
if (defined($slot{'startreserve'})
&& $slot{'startreserve'} > $slot{'starttime'}) {
@@ -1522,20 +3310,88 @@ 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 ($key eq 'maxspace') {
+ $slot{$key} =~ s/\D+//g;
+ }
}
}
-
+ 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;
@@ -1546,14 +3402,43 @@ sub csv_upload_assign {
$r->rflush();
$countdone++;
}
- $r->print("Created $countdone slots\n
");
+ 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
");
+ $r->print(''.$error.'
'."\n");
}
&show_table($r,$mgr);
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 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;
@@ -1565,16 +3450,86 @@ sub handler {
}
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
-
+
+ my %crumb_titles = &slot_command_titles();
+ my ($brcrum,$bread_crumbs_component);
+
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';
+ }
+ } 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.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",
+ text=>$crumb_titles{'showslots'},
+ help=>'Slot_Use'}];
+ $title = 'Managing Slots';
+ $bread_crumbs_component = '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'}}});
+ }
+ }
+ } else {
+ $brcrum =[];
}
- &start_page($r,$title);
-
- if ($env{'form.command'} eq 'showslots' && $vgr eq 'F') {
+ 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,$bread_crumbs_component,$js,$mgr);
+
+ if ($env{'form.command'} eq 'manageresv') {
+ $allavailable = $available;
+ undef($available);
+ undef($got_slots);
+ my $crstype = &Apache::loncommon::course_type();
+ &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') {
&show_table($r,$mgr);
} elsif ($env{'form.command'} eq 'remove_registration' && $mgr eq 'F') {
&remove_registration($r);
@@ -1601,6 +3556,8 @@ sub handler {
}
&csv_upload_map($r);
}
+ } elsif (($env{'form.command'} eq 'slotlog') && ($vgr eq 'F')) {
+ &show_reservations_log($r);
} else {
my $symb=&unescape($env{'form.symb'});
if (!defined($symb)) {
@@ -1621,22 +3578,44 @@ 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 {
- $r->print("Unknown command: ".$env{'form.command'}."
");
+ $r->print(''.&mt('Unknown command: [_1]',$env{'form.command'}).'
');
}
}
&end_page($r);