--- loncom/interface/slotrequest.pm 2006/05/12 05:12:27 1.61
+++ loncom/interface/slotrequest.pm 2018/07/02 20:34:52 1.139
@@ -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.61 2006/05/12 05:12:27 albertel Exp $
+# $Id: slotrequest.pm,v 1.139 2018/07/02 20:34:52 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -36,6 +36,8 @@ use Apache::lonlocal;
use Apache::lonnet;
use Apache::lonnavmaps();
use Date::Manip;
+use lib '/home/httpd/lib/perl/';
+use LONCAPA qw(:DEFAULT :match);
sub fail {
my ($r,$code)=@_;
@@ -54,8 +56,22 @@ sub fail {
}
sub start_page {
- my ($r,$title)=@_;
- $r->print(&Apache::loncommon::start_page($title));
+ my ($r,$title,$brcrum,$js)=@_;
+ my $args;
+ if (ref($brcrum) eq 'ARRAY') {
+ $args = {bread_crumbs => $brcrum};
+ }
+ if (($env{'form.requestattempt'}) || ($env{'form.command'} eq 'manageresv')) {
+ my %loaditems = (
+ onload => 'javascript:uncheckSlotRadio();',
+ );
+ if (ref($args) eq 'HASH') {
+ $args->{'add_entries'} = \%loaditems;
+ } else {
+ $args = { 'add_entries' => \%loaditems };
+ }
+ }
+ $r->print(&Apache::loncommon::start_page($title,$js,$args));
}
sub end_page {
@@ -63,6 +79,291 @@ sub end_page {
$r->print(&Apache::loncommon::end_page());
}
+sub reservation_js {
+ my ($slots,$consumed_uniqueperiods,$available,$got_slots,$symb) = @_;
+ return unless ((ref($slots) eq 'HASH') && (ref($available) eq 'ARRAY'));
+ my $toskip;
+ if ($symb eq '') {
+ $toskip = { symb => 1, };
+ }
+ my ($i,$j) = (0,0);
+ my $js;
+ foreach my $slot (sort
+ { return $slots->{$a}->{'starttime'} <=> $slots->{$b}->{'starttime'} }
+ (keys(%{$slots}))) {
+
+ next if (!&allowed_slot($slot,$slots->{$slot},$symb,$slots,
+ $consumed_uniqueperiods,$toskip));
+ $js .= " slotstart[$i]='$slots->{$slot}->{'starttime'}';\n".
+ " slotend[$i]='$slots->{$slot}->{'endtime'}';\n".
+ " slotname[$i]='$slot';\n";
+ if (($symb) && (ref($got_slots) eq 'ARRAY')) {
+ if (grep(/^\Q$slot\E$/,@{$got_slots})) {
+ $js .= " currslot[$j]='$slot';\n";
+ $j++;
+ }
+ }
+ $i++;
+ push(@{$available},$slot);
+ }
+ if ($j) {
+ $js = " var currslot = new Array($j);\n\n$js";
+ }
+ my %alerts = &Apache::lonlocal::texthash (
+ none => 'No reservable time slots found',
+ invalid => 'Invalid date format',
+ );
+ return <<"ENDSCRIPT";
+
+ENDSCRIPT
+
+}
+
+
=pod
slot_reservations db
@@ -75,7 +376,7 @@ sub end_page {
=cut
sub get_course {
- (undef,my $courseid)=&Apache::lonxml::whichuser();
+ (undef,my $courseid)=&Apache::lonnet::whichuser();
my $cdom=$env{'course.'.$courseid.'.domain'};
my $cnum=$env{'course.'.$courseid.'.num'};
return ($cnum,$cdom);
@@ -88,7 +389,7 @@ sub get_reservation_ids {
my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
"^$slot_name\0");
- if (&network_error(%consumed)) {
+ if (&Apache::lonnet::error(%consumed)) {
return 'error: Unable to determine current status';
}
my ($tmp)=%consumed;
@@ -115,7 +416,6 @@ sub check_for_reservation {
my ($symb,$mode)=@_;
my $student = &Apache::lonnet::EXT("resource.0.availablestudent", $symb,
$env{'user.domain'}, $env{'user.name'});
-
my $course = &Apache::lonnet::EXT("resource.0.available", $symb,
$env{'user.domain'}, $env{'user.name'});
my @slots = (split(/:/,$student), split(/:/, $course));
@@ -125,27 +425,26 @@ sub check_for_reservation {
my ($cnum,$cdom)=&get_course();
my %slots=&Apache::lonnet::get('slots', [@slots], $cdom, $cnum);
- if (&network_error($student) || &network_error($course) ||
- &network_error(%slots)) {
+ if (&Apache::lonnet::error($student)
+ || &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 {
@@ -162,8 +461,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();
@@ -173,7 +475,8 @@ sub get_consumed_uniqueperiods {
my $course = &Apache::lonnet::EXT("resource.0.available",
$symb, $env{'user.domain'},
$env{'user.name'});
- if (&network_error($student) || &network_error($course)) {
+ if (&Apache::lonnet::error($student)
+ || &Apache::lonnet::error($course)) {
return 'error: Unable to determine current status';
}
foreach my $slot (split(/:/,$student), split(/:/, $course)) {
@@ -184,7 +487,7 @@ sub get_consumed_uniqueperiods {
if (!ref($slots)) {
my ($cnum,$cdom)=&get_course();
my %slots=&Apache::lonnet::get('slots', [keys(%used_slots)], $cdom, $cnum);
- if (&network_error(%slots)) {
+ if (&Apache::lonnet::error(%slots)) {
return 'error: Unable to determine current status';
}
$slots = \%slots;
@@ -209,12 +512,19 @@ sub check_for_conflict {
if (!defined($new_slot->{'uniqueperiod'})) { return undef; }
if (!ref($consumed_uniqueperiods)) {
- $consumed_uniqueperiods = &get_consumed_uniqueperiods($slots);
- if (&network_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}};
@@ -225,36 +535,27 @@ sub check_for_conflict {
}
}
return undef;
-
-}
-
-sub network_error {
- my ($result) = @_;
- if ($result =~ /^(con_lost|no_such_host|error: [^2])/) {
- return 1;
- }
- return 0;
}
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 (&network_error($value) || &network_error($use_slots)) {
+ if (&Apache::lonnet::error($value)
+ || &Apache::lonnet::error($use_slots)) {
return 'error: Unable to determine current status';
}
my $parm_symb = $symb;
my $parm_level = 1;
- if ($use_slots eq 'map') {
+ if ($use_slots eq 'map' || $use_slots eq 'map_map') {
my ($map) = &Apache::lonnet::decode_symb($symb);
$parm_symb = &Apache::lonnet::symbread($map);
$parm_level = 2;
@@ -264,7 +565,7 @@ sub make_reservation {
if ($other_slot eq $slot_name) {
my %consumed=&Apache::lonnet::dump('slot_reservations', $cdom,
$cnum, "^$slot_name\0");
- if (&network_error($value)) {
+ if (&Apache::lonnet::error($value)) {
return 'error: Unable to determine current status';
}
my $me=$env{'user.name'}.':'.$env{'user.domain'};
@@ -281,7 +582,7 @@ sub make_reservation {
if (!defined($max)) { $max=99999; }
my (@ids)=&get_reservation_ids($slot_name);
- if (&network_error(@ids)) {
+ if (&Apache::lonnet::error(@ids)) {
return 'error: Unable to determine current status';
}
my $last=0;
@@ -311,13 +612,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;
}
@@ -325,6 +620,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::write_log('course','slotreservationslog',\%storehash,
+ '',$env{'user.name'},$env{'user.domain'},
+ $cnum,$cdom);
+ &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
+ 1,$env{'user.name'},$env{'user.domain'},
+ $env{'user.name'},$env{'user.domain'});
+
+ return;
+}
+
sub remove_registration {
my ($r) = @_;
if ($env{'form.entry'} ne 'remove all') {
@@ -336,13 +657,13 @@ sub remove_registration {
my ($cnum,$cdom)=&get_course();
my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
"^$slot_name\0");
- if (&network_error(%consumed)) {
- $r->print("
".&mt('A network error has occured.').'
'); + if (&Apache::lonnet::error(%consumed)) { + $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; } @@ -350,7 +671,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 { @@ -367,7 +688,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 { @@ -379,17 +700,19 @@ 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
- - @@ -415,7 +738,11 @@ sub release_all_slot { my ($result,$msg) = &release_reservation($slot_name,$uname,$udom, $consumed{$entry}{'symb'},$mgr); - $r->print("$msg
"); + if (!$result) { + $r->print(''.&mt($msg).'
'); + } else { + $r->print("$msg
"); + } $r->rflush(); } $r->print(''.
@@ -436,12 +763,16 @@ sub release_slot {
if ($mgr eq 'F'
&& defined($env{'form.symb'})) {
- $symb = $env{'form.symb'};
+ $symb = &unescape($env{'form.symb'});
}
my ($result,$msg) =
&release_reservation($slot_name,$uname,$udom,$symb,$mgr);
- $r->print(" $msg '.&mt($msg).' $msg '.
@@ -462,9 +793,31 @@ sub release_reservation {
return (0,&mt('Not allowed to release Reservation: [_1], as it has already ended.',$description));
}
}
- # get parameter string, check for existance, rebuild string with the slot
- my @slots = split(/:/,&Apache::lonnet::EXT("resource.0.availablestudent",
- $symb,$udom,$uname));
+
+ # if the reservation symb is for a map get a resource in that map
+ # to check slot parameters on
+ my $navmap=Apache::lonnavmaps::navmap->new;
+ if (!defined($navmap)) {
+ return (0,'error: Unable to determine current status');
+ }
+ my $passed_resource = $navmap->getBySymb($symb);
+ if (ref($passed_resource)) {
+ if ($passed_resource->is_map()) {
+ my ($a_resource) =
+ $navmap->retrieveResources($passed_resource,
+ sub {$_[0]->is_problem() || $_[0]->is_tool() },0,1);
+ $symb = $a_resource->symb();
+ }
+ } else {
+ unless ($mgr eq 'F') {
+ return (0,'error: Unable to determine current status');
+ }
+ }
+
+ # get parameter string, check for existence, rebuild string with the slot
+ my $student = &Apache::lonnet::EXT("resource.0.availablestudent",
+ $symb,$udom,$uname);
+ my @slots = split(/:/,$student);
my @new_slots;
foreach my $exist_slot (@slots) {
@@ -482,18 +835,29 @@ 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::write_log('course','slotreservationslog',
+ \%storehash,1,$uname,$udom,$cnum,$cdom);
+ &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',
+ \%storehash,1,$uname,$udom,$uname,$udom);
}
}
- my $use_slots = &Apache::lonnet::EXT("resource.0.useslots");
+ my $use_slots = &Apache::lonnet::EXT("resource.0.useslots",
+ $symb,$udom,$uname);
&Apache::lonxml::debug("use_slots is $use_slots Slot $slot_name marked as deleted. '.&mt('Slot [_1] marked as deleted.',''.$slot_name.'').' An error ($ret) occurse when attempting to delete Slot $slot_name. '.&mt('An error occurred when attempting to delete slot: [_1]',''.$slot_name.'')." ($ret) Slot $slot_name has active reservations. '.&mt('Slot [_1] has active reservations.',''.$slot_name.'').' Slot $slot_name does not exist. '.&mt('Slot [_1] does not exist.',''.$slot_name.'').' '.
@@ -546,103 +913,142 @@ sub delete_slot {
sub return_link {
my ($r) = @_;
- $r->print(' '.
- &mt('Return to last resource').' '.
+ &mt('Return to reservations'));
+ } else {
+ $r->print(' '.
+ &mt('Return to last resource').' An error occured while attempting to make a reservation. ($1) '
+ .&mt('An error occurred while attempting to make a reservation. ([_1])',$1)
+ .' Already have a reservation: $description1 '.&mt('You already have a reservation: "[_1]", assigned by your instructor.',
+ $description1).' '.&mt('Your instructor must unassign it before you can make a new reservation.').
+ '
-
-or
-
");
- if (&network_error($use_slots)) {
+ if (&Apache::lonnet::error($use_slots)) {
return (0,'error: Unable to determine current status');
}
my $parm_level = 1;
- if ($use_slots eq 'map') {
+ if ($use_slots eq 'map' || $use_slots eq 'map_map') {
$parm_level = 2;
}
# store new parameter string
@@ -501,12 +865,15 @@ 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");
} else {
- $msg = &mt('Released Reservation: [_1]',$description);
+ $msg = ''.&mt('Released reservation: [_1]',$description).'
';
+ my $person = &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'});
+ my $subject = &mt('Reservation change: [_1]',$description);
+ my $msgbody = &mt('Reservation released by [_1] for [_2].',$person,$description);
+ $msg .= &slot_change_messaging($slot{'reservationmsg'},$subject,$msgbody,'release');
}
return (1,$msg);
}
@@ -528,15 +895,15 @@ sub delete_slot {
my $ret = &Apache::lonnet::cput('slots', {$slot_name => \%slot},
$cdom, $cnum);
if ($ret eq 'ok') {
- $r->print("
' + .&mt('No slots have been created in this '.lc($crstype).'.') + .'
' + ); + return; + } my %Saveable_Parameters = ('show' => 'array', 'when' => 'scalar', @@ -919,18 +1490,26 @@ sub show_table { 'starttime' => 'Start time', 'endtime' => 'End Time', 'startreserve' => 'Time students can start reserving', + 'endreserve' => 'Time students can no longer reserve', + 'reservationmsg' => 'Message triggered by reservation', 'secret' => 'Secret Word', - 'maxspace' => 'Maximum # of students', + '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','maxspace','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') @@ -977,13 +1556,16 @@ 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'; my $hide_radio = &Apache::lonhtmlcommon::radio('deleted',$env{'form.deleted'},'hide'); my $show_radio = &Apache::lonhtmlcommon::radio('deleted',$env{'form.deleted'},'show'); - $r->print('