--- loncom/interface/slotrequest.pm 2018/01/31 15:28:47 1.137 +++ loncom/interface/slotrequest.pm 2025/04/02 23:44:01 1.152 @@ -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.137 2018/01/31 15:28:47 raeburn Exp $ +# $Id: slotrequest.pm,v 1.152 2025/04/02 23:44:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -50,16 +50,23 @@ sub fail { } else { $r->print('<p>'.&mt('Failed.').'</p>'); } - + &return_link($r); &end_page($r); } sub start_page { - my ($r,$title,$brcrum,$js)=@_; + 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.context'} eq 'user')) && + ($env{'form.symb'})) { + $args->{'bread_crumbs_nomenu'} = 1; + } } if (($env{'form.requestattempt'}) || ($env{'form.command'} eq 'manageresv')) { my %loaditems = ( @@ -71,12 +78,40 @@ sub start_page { $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'}); + if ($symb =~ m{^/enc/}) { + $symb = &Apache::lonenc::unencrypted($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 { my ($r)=@_; - $r->print(&Apache::loncommon::end_page()); + $r->print('</div>'.&Apache::loncommon::end_page()); } sub reservation_js { @@ -256,7 +291,7 @@ function uncheckSlotRadio() { } if (slotpicks.length) { for (var i=0; i<slotpicks.length; i++) { - slotpicks[i].checked = false; + slotpicks[i].checked = false; } } } @@ -305,7 +340,7 @@ function toggleSlotMap(maprownum,rownum) for (var i=0; i<resrows.length; i++) { resrows[i].style.display = rowdisplay; if (rowdisplay == 'table-row') { - mapbgidx ++; + mapbgidx ++; var bgcolnew = mapbgidx % 2; var bgcolold = (mapbgidx+1) % 2; var k = i+parseInt(rownum)+1; @@ -340,7 +375,7 @@ function toggleSlotMap(maprownum,rownum) if (table.rows[i].style.display != 'none') { idx ++; var bgcolnew = idx % 2; - var bgcolold = (idx+1) % 2; + var bgcolold = (idx+1) % 2; j = i+1; if (document.getElementById('LC_slotmaprow_'+j)) { document.getElementById('LC_slotmaprow_'+j).className = rowclasses[bgcolnew]; @@ -384,7 +419,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, @@ -429,7 +464,7 @@ sub check_for_reservation { || &Apache::lonnet::error($course) || &Apache::lonnet::error(%slots)) { return 'error: Unable to determine current status'; - } + } my @got; my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots,'starttime'); foreach my $slot_name (@sorted_slots) { @@ -553,18 +588,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'; } @@ -590,17 +625,17 @@ sub make_reservation { my $num=(split('\0',$id))[1]; if ($num > $last) { $last=$num; } } - + my $wanted=$last+1; &Apache::lonxml::debug("wanted $wanted<br />"); 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" => @@ -612,7 +647,9 @@ sub make_reservation { if ($value) { $new_value=$value.':'.$new_value; } - &store_slot_parm($symb,$slot_name,$parm_level,$new_value,$cnum,$cdom); + 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; } @@ -621,29 +658,27 @@ sub make_reservation { } 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'}); + 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, + symb => $symb_for_db, slot => $slot_name, - action => 'reserve', - context => $env{'form.context'}, + action => $action, + context => $context, ); &Apache::lonnet::write_log('course','slotreservationslog',\%storehash, - '',$env{'user.name'},$env{'user.domain'}, - $cnum,$cdom); + $delflag,$uname,$udom,$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; + $delflag,$uname,$udom,$uname,$udom); + return $result; } sub remove_registration { @@ -676,17 +711,21 @@ sub remove_registration { sub remove_registration_user { my ($r) = @_; - + my $slot_name = $env{'form.slotname'}; my $name = &Apache::loncommon::plainname($env{'form.uname'}, $env{'form.udom'}); - my $title = &Apache::lonnet::gettitle($env{'form.symb'}); + my $symb = &unescape($env{'form.symb'}); + if ($symb =~ m{^/enc/}) { + $symb = &Apache::lonenc::unencrypted($symb); + } + my $title = &Apache::lonnet::gettitle($symb); my $msg = &mt('Remove [_1] from slot [_2] for [_3]', $name,$slot_name,$title); - + &remove_registration_confirmation($r,$msg,['uname','udom','slotname', 'entry','symb','context']); } @@ -722,14 +761,14 @@ END_CONFIRM sub release_all_slot { my ($r,$mgr)=@_; - + my $slot_name = $env{'form.slotname'}; my ($cnum,$cdom)=&get_course(); my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum, "^$slot_name\0"); - + $r->print('<p>'.&mt('Releasing reservations').'</p>'); foreach my $entry (sort { $consumed{$a}{'name'} cmp @@ -739,9 +778,9 @@ sub release_all_slot { &release_reservation($slot_name,$uname,$udom, $consumed{$entry}{'symb'},$mgr); if (!$result) { - $r->print('<p><span class="LC_error">'.&mt($msg).'</span></p>'); + $r->print('<p class="LC_error">'.&mt($msg).'</p>'); } else { - $r->print("<p>$msg</p>"); + $r->print($msg); } $r->rflush(); } @@ -764,16 +803,19 @@ sub release_slot { if ($mgr eq 'F' && defined($env{'form.symb'})) { $symb = &unescape($env{'form.symb'}); + if ($symb =~ m{^/enc/}) { + $symb = &Apache::lonenc::unencrypted($symb); + } } my ($result,$msg) = &release_reservation($slot_name,$uname,$udom,$symb,$mgr); if (!$result) { - $r->print('<p><span class="LC_error">'.&mt($msg).'</span></p>'); + $r->print('<p class="LC_error">'.&mt($msg).'</p>'); } else { $r->print("<p>$msg</p>"); } - + if ($mgr eq 'F') { $r->print('<p><a href="/adm/slotrequest?command=showslots">'. &mt('Return to slot list').'</a></p>'); @@ -787,26 +829,184 @@ sub release_reservation { my ($slot_name,$uname,$udom,$symb,$mgr) = @_; my %slot=&Apache::lonnet::get_slot($slot_name); my $description=&get_description($slot_name,\%slot); + my $msg; if ($mgr ne 'F') { if ($slot{'starttime'} < time) { - return (0,&mt('Not allowed to release Reservation: [_1], as it has already ended.',$description)); + return (0,&mt('Not allowed to release Reservation: [_1], as it has already started.',$description)); } } + my $context = $env{'form.context'}; - # if the reservation symb is for a map get a resource in that map - # to check slot parameters on + # get navmap object my $navmap=Apache::lonnavmaps::navmap->new; if (!defined($navmap)) { return (0,'error: Unable to determine current status'); } + + my ($cnum,$cdom)=&get_course(); + + # get slot reservations, check if user has reservation + my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum, + "^$slot_name\0"); + + # + # If release is because of a reservation *change*, symb(s) associated with reservation + # being dropped may differ from the current symb. + # + # We need to get symb(s) from slot_reservations.db, and for each symb, update + # the value of the availablestudent parameter, at the appropriate level + # (as dictated by the value of the useslots parameter for the symb and user). + # + # We also delete all entries for the slot being released, for the specific user. + # + + my $conflict; + + if (($env{'form.command'} eq 'change') && ($slot_name eq $env{'form.releaseslot'}) && + ($env{'form.slotname'} ne $slot_name)) { + my %changedto = &Apache::lonnet::get_slot($env{'form.slotname'}); + + # check for conflicts + my ($to_uniq_start,$to_uniq_end,$from_uniq_start,$from_uniq_end); + if (ref($changedto{'uniqueperiod'}) eq 'ARRAY') { + ($to_uniq_start,$to_uniq_end) = @{$changedto{'uniqueperiod'}}; + } + if (ref($slot{'uniqueperiod'}) eq 'ARRAY') { + ($from_uniq_start,$from_uniq_end) = @{$slot{'uniqueperiod'}}; + } + my $to_start = $changedto{'starttime'}; + my $to_end = $changedto{'endtime'}; + my $from_start = $slot{'starttime'}; + my $from_end = $slot{'endtime'}; + + if (! + ($from_start < $to_uniq_start && $from_end < $to_uniq_start) || + ($from_start > $to_uniq_end && $from_end > $to_uniq_end )) { + $conflict = 1; + } + if (! + ($to_start < $from_uniq_start && $to_end < $from_uniq_start) || + ($to_start > $from_uniq_end && $to_end > $from_uniq_end )) { + $conflict = 1; + } + + if ($conflict) { + my %symbs_for_slot; + my (%to_delete,%failed,%released); + foreach my $entry (keys(%consumed)) { + if ( $consumed{$entry}->{'name'} eq ($uname.':'.$udom) ) { + $symbs_for_slot{$consumed{$entry}->{'symb'}} = 1; + $to_delete{$entry} = 1; + } + } + if (keys(%to_delete)) { + my @removals = keys(%to_delete); + if (&Apache::lonnet::del('slot_reservations',\@removals, + $cdom,$cnum) eq 'ok') { + foreach my $item (keys(%symbs_for_slot)) { + my $result = &update_selectable($navmap,$slot_name,$item,$cdom, + $cnum,$udom,$uname,$context); + if ($result =~ /^error/) { + $failed{$item} = 1; + } else { + $released{$item} = 1; + } + } + } + } + if (keys(%released)) { + $msg = '<span style="font-weight: bold;">'. + &mt('Released Reservation: [_1]',$description).'</span> '. + &mt('The following items had their reservation status change').':'; + my (%folders,%pages,%container,%titles); + foreach my $item (keys(%released)) { + my $res = $navmap->getBySymb($item); + if (ref($res)) { + $titles{$item} = $res->title(); + if ($res->is_map()) { + $folders{$item}{'title'} = $titles{$item}; + if ($res->is_page()) { + $pages{$item}{'title'} = $titles{$item}; + } else { + $folders{$item}{'title'} = $titles{$item}; + } + } else { + my $mapsrc = $res->enclosing_map_src(); + my $map = $navmap->getResourceByUrl($mapsrc); + if (ref($map)) { + if ($map->id() eq '0.0') { + $container{$mapsrc}{'title'} &mt('Top level of course'); + } else { + $container{$mapsrc}{'title'} = $map->title(); + if ($map->is_page()) { + $container{$mapsrc}{'page'} = 1; + } + } + } + $container{$mapsrc}{'resources'}{$item} = 1; + } + } + } + $msg .= '<ul>'; + if (keys(%folders)) { + $msg .= '<li>'.&mt('Folders').': '. + join(', ', map { $folders{$_}{'title'} } (sort { $folders{$b}{'title'} cmp $folders{$a}{'title'} } (keys(%folders)))). + '</li>'; + } + if (keys(%pages)) { + $msg .= '<li>'.&mt('Composite Pages').': '. + join(', ', map { $pages{$_}{'title'} } (sort { $pages{$b}{'title'} cmp $pages{$a}{'title'} } (keys(%pages)))). + '</li>'; + } + if (keys(%container)) { + $msg .= '<li>'.&mt('Resources').':<ul>'; + foreach my $key (sort { $container{$b}{'title'} cmp $container{$a}{'title'} } (keys(%container))) { + if (ref($container{$key}{'resources'}) eq 'HASH') { + $msg .= '<li>'. + join(', ', map { $titles{$_} } (sort(keys(%{$container{$key}{'resources'}})))); + if ($container{$key}{'page'}) { + $msg .= ' '.&mt('(in composite page [_1])',$container{$key}{'title'}).'</li>'; + } else { + $msg .= ' '.&mt('(in folder [_1])',$container{$key}{'title'}).'</li>'; + } + } + } + $msg .= '</ul></li>'; + } + $msg .= '</ul>'; + 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); + } else { + if (keys(%to_delete)) { + $msg = &mt('Reservation release partially complete for [_1]',$description); + } else { + $msg = &mt('No entries found for this user to release for [_1].',$description); + } + return (0,$msg); + } + } else { + $msg = &mt('No conflict found; not releasing: [_1].',$description); + return (0,$msg); + } + } + + my $map_symb; + my $parm_symb = $symb; my $passed_resource = $navmap->getBySymb($symb); + + # if the reservation symb is for a map get a resource in that map + # to check slot parameters on + my $parm_level = 1; 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(); + sub {$_[0]->is_problem() || $_[0]->is_tool() },0,1); + $parm_symb = $a_resource->symb(); } } else { unless ($mgr eq 'F') { @@ -814,68 +1014,133 @@ sub release_reservation { } } - # 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) { - if ($exist_slot eq $slot_name) { next; } - push(@new_slots,$exist_slot); + # Get value of useslots parameter in effect for this user. + # If value is map or map_map, then the parm level is 2 (i.e., + # non-recursive enclosing map/folder level for specific user) + # and the symb for this reservation in slot_reservations.db + # will be the symb of the map itself. + + my $use_slots = &Apache::lonnet::EXT('resource.0.useslots', + $parm_symb,$udom,$uname); + if (&Apache::lonnet::error($use_slots)) { + return (0,'error: Unable to determine current status'); + } + if ($use_slots eq 'map' || $use_slots eq 'map_map') { + $parm_level = 2; + if ($passed_resource->is_map()) { + $map_symb = $passed_resource->symb(); + } else { + my ($map) = &Apache::lonnet::decode_symb($symb); + $map_symb = &Apache::lonnet::symbread($map); + } } - my $new_param = join(':',@new_slots); - my ($cnum,$cdom)=&get_course(); + # + # If release is *not* because of a reservation change, i.e., this is a "drop" + # by a student, or a removal for a single student by an instructor then + # only remove one entry from slot_reservations.db, where both the user + # and the symb match the current context. If useslots was set to map or + # map_map, then the symb to match in slot_reservations.db is the symb of + # the enclosing map/folder, not the symb of the resource. + # - # get slot reservations, check if user has one, if so remove reservation - my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum, - "^$slot_name\0"); + my ($match,$symb_to_check); + if ($parm_level == 2) { + $symb_to_check = $map_symb; + } else { + $symb_to_check = $parm_symb; + } foreach my $entry (keys(%consumed)) { - 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('slotreservationslog',\%storehash, - 1,$uname,$udom,$cnum,$cdom); - &Apache::lonnet::write_log($cdom.'_'.$cnum.'_slotlog',\%storehash, - 1,$uname,$udom,$uname,$udom); - } + if ( $consumed{$entry}->{'name'} eq ($uname.':'.$udom) ) { + if ($consumed{$entry}->{'symb'} eq $symb_to_check) { + if (&Apache::lonnet::del('slot_reservations',[$entry], + $cdom,$cnum) eq 'ok') { + $match = $symb_to_check; + } + last; + } + } } + if ($match) { + if (&update_selectable($navmap,$slot_name,$symb,$cdom, + $cnum,$udom,$uname,$context) =~ /^error/) { + if ($mgr eq 'F') { + $msg = &mt('Reservation release partially complete for: [_1]',"$uname:$udom").'<br />'. + &mt('Update of availablestudent parameter for [_1] was not completed.',"$uname:$udom"); + } else { + $msg = &mt('Release partially complete for: [_1]',$description); + } + return (0,$msg); + } else { + if ($mgr eq 'F') { + $msg = &mt('Released Reservation for user: [_1]',"$uname:$udom"); + } else { + $msg = '<p style="font-weight: bold;">'. + &mt('Released reservation: [_1]',$description).'</p>'; + 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); + } + } else { + $msg = &mt('Release failed for: [_1]',$description); + return (0,$msg); + } +} + +sub update_selectable { + my ($navmap,$slot_name,$symb,$cdom,$cnum,$udom,$uname,$context) = @_; + return 'error: ' unless (ref($navmap)); + my $symb_for_parm = $symb; + my $passed_resource = $navmap->getBySymb($symb); + return 'error: invalid symb' unless (ref($passed_resource)); + + # if the reservation symb is for a map get a resource in that map + # to check slot parameters on + if ($passed_resource->is_map()) { + my ($a_resource) = + $navmap->retrieveResources($passed_resource, + sub {$_[0]->is_problem() || $_[0]->is_tool() },0,1); + $symb_for_parm = $a_resource->symb(); + } + # get parameter string, check for existence, rebuild string with the slot + my $student = &Apache::lonnet::EXT('resource.0.availablestudent', + $symb_for_parm,$udom,$uname); + + # Get value of useslots parameter in effect for this user. + # If value is map or map_map, then the parm level is 2 (i.e., + # non-recursive enclosing map/folder level for specific user) + # and the symb for this reservation in slot_reservations.db + # will be the symb of the map itself. - my $use_slots = &Apache::lonnet::EXT("resource.0.useslots", - $symb,$udom,$uname); + my $use_slots = &Apache::lonnet::EXT('resource.0.useslots', + $symb_for_parm,$udom,$uname); &Apache::lonxml::debug("use_slots is $use_slots<br />"); - if (&Apache::lonnet::error($use_slots)) { - return (0,'error: Unable to determine current status'); + if (&Apache::lonnet::error($use_slots)) { + return 'error: Unable to determine current status'; } my $parm_level = 1; if ($use_slots eq 'map' || $use_slots eq 'map_map') { - $parm_level = 2; + $parm_level = 2; } - # store new parameter string - my $result=&Apache::lonparmset::storeparm_by_symb($symb, - '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 = '<span style="font-weight: bold;">'.&mt('Released reservation: [_1]',$description).'</span><br /><br />'; - 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'); + + my @slots = split(/:/,$student); + + my @new_slots; + foreach my $exist_slot (@slots) { + next if ($exist_slot eq $slot_name); + push(@new_slots,$exist_slot); } - return (1,$msg); + my $new_value = join(':',@new_slots); + + my $result = &store_slot_parm($symb_for_parm,$symb,$slot_name,$parm_level, + $new_value,$cnum,$cdom,$uname,$udom,'release', + $context,1); + return $result; } sub delete_slot { @@ -897,7 +1162,7 @@ sub delete_slot { if ($ret eq 'ok') { $r->print('<p>'.&mt('Slot [_1] marked as deleted.','<tt>'.$slot_name.'</tt>').'</p>'); } else { - $r->print('<p><span class="LC_error">'.&mt('An error occurred when attempting to delete slot: [_1]','<tt>'.$slot_name.'</tt>')." ($ret)</span></p>"); + $r->print('<p class="LC_error">'.&mt('An error occurred when attempting to delete slot: [_1]','<tt>'.$slot_name.'</tt>')." ($ret)</p>"); } } else { if (%consumed) { @@ -913,15 +1178,32 @@ sub delete_slot { sub return_link { my ($r) = @_; + my $target = &return_target(); if (($env{'form.command'} eq 'manageresv') || ($env{'form.context'} eq 'usermanage')) { - $r->print('<p><a href="/adm/slotrequest?command=manageresv">'. - &mt('Return to reservations')); + $r->print('<p><a href="/adm/slotrequest?command=manageresv" target="'.$target.'">'. + &mt('Return to reservations').'</a></p>'); } else { - $r->print('<p><a href="/adm/flip?postdata=return:">'. + $r->print('<p><a href="/adm/flip?postdata=return:" target="'.$target.'">'. &mt('Return to last resource').'</a></p>'); } } +sub return_target { + my ($target,$ltitarget,$deeplinktarget); + if ($env{'request.lti.login'}) { + $ltitarget = $env{'request.lti.target'}; + } + if ($env{'request.deeplink.login'}) { + $deeplinktarget = $env{'request.deeplink.target'}; + } + if (($ltitarget eq 'iframe') || ($deeplinktarget eq '_self')) { + $target = '_self'; + } else { + $target = '_top'; + } + return $target; +} + sub get_slot { my ($r,$symb,$conflictable_slot,$inhibit_return_link)=@_; @@ -929,18 +1211,24 @@ sub get_slot { my $slot_name=&check_for_conflict($symb,$env{'form.slotname'},\%slot); if ($slot_name =~ /^error: (.*)/) { - $r->print('<p><span class="LC_error">' + $r->print('<p class="LC_error">' .&mt('An error occurred while attempting to make a reservation. ([_1])',$1) - .'</span></p>'); + .'</p>'); &return_link($r); return 0; } if ($slot_name && $slot_name ne $conflictable_slot) { my %slot=&Apache::lonnet::get_slot($slot_name); my $description1=&get_description($slot_name,\%slot); + my $slottype1=$slot{'type'}; %slot=&Apache::lonnet::get_slot($env{'form.slotname'}); my $description2=&get_description($env{'form.slotname'},\%slot); - if ($slot_name ne $env{'form.slotname'}) { + if ($slottype1 eq 'preassigned') { + $r->print('<p>'.&mt('You already have a reservation: "[_1]", assigned by your instructor.', + $description1).'</p>'. + '<p>'.&mt('Your instructor must unassign it before you can make a new reservation.'). + '</p>'); + } elsif ($slot_name ne $env{'form.slotname'}) { $r->print(<<STUFF); <form method="post" action="/adm/slotrequest"> <input type="hidden" name="symb" value="$env{'form.symb'}" /> @@ -978,9 +1266,9 @@ STUFF if (defined($reserved)) { my $retvalue = 0; if ($slot_name =~ /^error: (.*)/) { - $r->print('<p><span class="LC_error">' + $r->print('<p class="LC_error">' .&mt('An error occurred while attempting to make a reservation. ([_1])',$1) - .'</span></p>'); + .'</p>'); } elsif ($reserved > -1) { $r->print('<p style="font-weight: bold;">'.&mt('Successfully signed up: [_1]',$description).'</p>'); $retvalue = 1; @@ -1067,7 +1355,7 @@ sub allowed_slot { if (($slot->{'endreserve'}) && ($slot->{'endreserve'} < time)) { return 0; - } + } &Apache::lonxml::debug("$slot_name reserve good"); my $userallowed=0; @@ -1173,9 +1461,10 @@ sub show_choices { return; } if (!@{$available}) { - $output = '<span class="LC_info">'.&mt('No available times.').'</span>'; + $output = '<p class="LC_info">'.&mt('No available times.').'</p>'; if ($env{'form.command'} ne 'manageresv') { - $output .= ' <a href="/adm/flip?postdata=return:">'. + my $target = &return_target(); + $output .= ' <a href="/adm/flip?postdata=return:" target="'.$target.'">'. &mt('Return to last resource').'</a>'; } if ($class) { @@ -1183,6 +1472,10 @@ sub show_choices { } else { return $output; } + } elsif ($env{'form.command'} ne 'manageresv') { + my $title = &Apache::lonnet::gettitle($symb); + my $headertext = &mt('Manage Reservation(s) for [_1]',$title); + $output .= '<h2 class="LC_heading_3">'.$headertext.'</h2>'; } if (@{$available} > 1) { my $numavailable = scalar(@{$available}); @@ -1199,7 +1492,7 @@ sub show_choices { } } my $showfilter = 'none'; - $output .= '<fieldset><legend>'.&mt('Actions').'</legend>'."\n". + $output .= '<fieldset><legend>'.&mt('Actions').':</legend>'."\n". '<form method="post" name="reservationdisplay_'.$num. '" action="" onsubmit="toggleSlotDisplay(this.form,'."'$num'".');">'; my @options = ('all','filter'); @@ -1213,7 +1506,7 @@ sub show_choices { ); foreach my $option (@options) { my $onclick = "toggleSlotDisplay(this.form,'$num');"; - if (($option eq 'show') && ($env{'form.command'} eq 'manageresv')) { + if (($option eq 'show') && ($env{'form.command'} eq 'manageresv')) { $onclick .= "currSlotDisplay$num(this.form,'$num');"; } $output .= '<span class="LC_nobreak"><label>'. @@ -1233,7 +1526,7 @@ sub show_choices { // <![CDATA[ function currSlotDisplay$num() { var currslot = new Array($numreserved); -$js +$js for (var j=0; j<$numreserved; j++) { if (document.getElementById('LC_slotrow_$num\_'+currslot[j])) { document.getElementById('LC_slotrow_$num\_'+currslot[j]).style.display = ''; @@ -1248,19 +1541,32 @@ ENDSCRIPT $output .= '<div id="LC_slotfilter_'.$num.'" style="display:'.$showfilter.'">'. '<form method="post" name="'.$chooserform.'" action="">'. - '<table><tr><td>'.&mt('Open after').'</td><td>'. + '<table class="LC_manage_reservations"><tr><th>'.&mt('Open after').'</th><td>'. &Apache::lonhtmlcommon::date_setter($chooserform,'start',$starttime,'','','','','','','',1,1). - '</td></tr><tr><td>'.&mt('Closed before').'</td><td>'. + '</td></tr><tr><th>'.&mt('Closed before').'</th><td>'. &Apache::lonhtmlcommon::date_setter($chooserform,'end',$endtime,'','','','','','','',1,1). '</td></tr></table><br />'. '<input type="button" name="slotfilter" value="Search for reservable slots" onclick="updateSlotDisplay(this.form,'."'$num'".');" />'. '</form></div><div id="LC_slotsearch_'.$num.'" style="display:none"><hr />'; } if ($env{'form.command'} eq 'manageresv') { - $output .= '<table border="0">'; + $output .= '<table border="0" class="LC_manage_reservations">'. + '<tr><th>'.&mt('Action').'</th><th>'.&mt('Name').'</th></tr>'; } else { - $output .= &Apache::loncommon::start_data_table(); + $output .= &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '<th>'.&mt('Action').'</th><th>'.&mt('Name').'</th>'. + &Apache::loncommon::end_data_table_header_row(); + } + my $shownsymb; + if ($env{'request.role.adv'}) { + $shownsymb = $symb; + } elsif (&Apache::lonnet::EXT('resource.0.encrypturl',$symb) =~ /^yes$/i) { + $shownsymb = &Apache::lonenc::encrypted($symb); + } else { + $shownsymb = $symb; } + $shownsymb = &escape($shownsymb); foreach my $slot (@{$available}) { my $description=&get_description($slot,$slots->{$slot}); my $form; @@ -1285,7 +1591,6 @@ ENDSCRIPT } } } - my $escsymb=&escape($symb); if (!$form) { my $name; if ($formname) { @@ -1298,7 +1603,7 @@ ENDSCRIPT $form=<<STUFF; <form method="post" action="/adm/slotrequest" $name> <input type="submit" name="Select" value="$text" /> - <input type="hidden" name="symb" value="$escsymb" /> + <input type="hidden" name="symb" value="$shownsymb" /> <input type="hidden" name="slotname" value="$slot" /> <input type="hidden" name="command" value="$command" /> <input type="hidden" name="context" value="$context" /> @@ -1396,7 +1701,7 @@ sub to_show { } return 0; } - + return 1; } @@ -1411,11 +1716,20 @@ sub remove_link { undef($udom); } + my $shownsymb; + if ($env{'request.role.adv'}) { + $shownsymb = $symb; + } elsif (&Apache::lonnet::EXT('resource.0.encrypturl',$symb) =~ /^yes$/i) { + $shownsymb = &Apache::lonenc::encrypted($symb); + } else { + $shownsymb = $symb; + } + $slotname = &escape($slotname); $entry = &escape($entry); $uname = &escape($uname); $udom = &escape($udom); - $symb = &escape($symb); + $symb = &escape($shownsymb); return <<"END_LINK"; <a href="/adm/slotrequest?command=remove_registration&slotname=$slotname&entry=$entry&uname=$uname&udom=$udom&symb=$symb&context=manage" @@ -1435,10 +1749,6 @@ sub show_table { } my $available; if ($mgr eq 'F') { - # FIXME: This line should be deleted once Slots uses breadcrumbs - $r->print('<br />'.&Apache::loncommon::help_open_topic( - 'Slot About', &mt('Help on slots'))); - $r->print('<div>'); $r->print('<form method="post" action="/adm/slotrequest"> <input type="hidden" name="command" value="uploadstart" /> @@ -1448,7 +1758,7 @@ sub show_table { $r->print('<form method="post" action="/adm/helper/newslot.helper"> <input type="submit" name="newslot" value="'.&mt('Create a New Slot').'" /> </form>'); - $r->print(&Apache::loncommon::help_open_topic('Slot AddInterface')); + $r->print(&Apache::loncommon::help_open_topic('Slot About')); $r->print('</div>'); } @@ -1460,7 +1770,7 @@ sub show_table { ); return; } - + my %Saveable_Parameters = ('show' => 'array', 'when' => 'scalar', 'order' => 'scalar', @@ -1550,7 +1860,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'; @@ -1563,40 +1873,36 @@ sub show_table { <input type="hidden" name="command" value="showslots" />'); $r->print('<div>'); $r->print('<table class="inline"> - <tr><th>'.&mt('Show').'</th> - <th>'.&mt('Student Display').'</th> - <th>'.&mt('Open').'</th> - <th>'.&mt('Slot Name Filter').'</th> + <tr><th><label for="show">'.&mt('Show').'</label></th> + <th><label for="studisplay">'.&mt('Student Display').'</label></th> + <th><label for="when">'.&mt('Open').'</label></th> + <th><label for="name_filter_type">'.&mt('Slot Name Filter').'</label></th> <th>'.&mt('Options').'</th> </tr> - <tr><td valign="top">'.&Apache::loncommon::multiple_select_form('show',\@show,6,\%show_fields,\@show_order). + <tr><td valign="top">'.&Apache::loncommon::multiple_select_form('show',\@show,6,\%show_fields,\@show_order,'show'). '</td> <td valign="top"> '.&Apache::loncommon::multiple_select_form('studisplay',\@stu_display, 6,\%stu_display_fields, - \@stu_display_order).' + \@stu_display_order,'studisplay').' </td> - <td valign="top">'.&Apache::loncommon::select_form($when,'when',\%when_fields). + <td valign="top">'.&Apache::loncommon::select_form($when,'when',\%when_fields,'','','when'). '</td> - <td valign="top">'.&Apache::loncommon::select_form($name_filter_type, + <td valign="top"><span class="LC_nobreak">'.&Apache::loncommon::select_form($name_filter_type, 'name_filter_type', - \%name_filter_type_fields). - '<br />'. + \%name_filter_type_fields,'','','name_filter_type'). + ' '. &Apache::lonhtmlcommon::textbox('name_filter_value', $env{'form.name_filter_value'}, - 15). - '</td> + 15,'aria-label="'.&mt('Name filter').'"'). + '</span></td> <td valign="top"> - <table> - <tr> - <td rowspan="2">'.&mt('Deleted slots:').'</td> - <td><label>'.$show_radio.&mt('Show').'</label></td> - </tr> - <tr> - <td><label>'.$hide_radio.&mt('Hide').'</label></td> - </tr> - </table> - </td> + <fieldset class="LC_delete_slot"> + <legend>'.&mt('Deleted slots').'</legend> + <span class="LC_nobreak"><label>'.$show_radio.&mt('Show').'</label> + <label>'.$hide_radio.&mt('Hide').'</label></span> + </fieldset> + </td> </tr> </table>'); $r->print('</div>'); @@ -1604,7 +1910,7 @@ sub show_table { my $linkstart='<a href="/adm/slotrequest?command=showslots&order='; my $tableheader = &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row().' - <th></th>'; + <th><span class="LC_visually_hidden">'.&mt('Action').'</span></th>'; foreach my $which (@show_order) { if ($which ne 'proctor' && exists($show{$which})) { $tableheader .= '<th>'.$linkstart.$which.'">'.$show_fields{$which}.'</a></th>'; @@ -1630,7 +1936,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] @@ -1664,7 +1970,7 @@ sub show_table { } my $description=&get_description($slot,$slots{$slot}); my ($id_count,$ids); - + if (exists($show{'scheduled'}) || exists($show{'space'}) ) { my $re_str = "$slot\0"; my @this_slot = grep(/^\Q$re_str\E/,keys(%consumed)); @@ -1771,11 +2077,11 @@ sub show_table { my ($edit,$delete,$showlog,$remove_all); if ($mgr) { $edit=(<<"EDITLINK"); -<a href="/adm/helper/newslot.helper?name=$slot">$lt{'edit'}</a> +<p class="LC_medium_line"><a href="/adm/helper/newslot.helper?name=$slot">$lt{'edit'}</a></p> EDITLINK $delete=(<<"DELETELINK"); -<a href="/adm/slotrequest?command=delete&slotname=$slot">$lt{'delete'}</a> +<p class="LC_medium_line"><a href="/adm/slotrequest?command=delete&slotname=$slot">$lt{'delete'}</a></p> DELETELINK $remove_all=&remove_link($slot,'remove all').'<br />'; @@ -1788,7 +2094,7 @@ DELETELINK } $showlog=(<<"LOGLINK"); -<a href="/adm/slotrequest?command=slotlog&slotname=$slot">$lt{'slotlog'}</a> +<p class="LC_medium_line"><a href="/adm/slotrequest?command=slotlog&slotname=$slot">$lt{'slotlog'}</a></p> LOGLINK if ($slots{$slot}{'type'} ne 'schedulable_student') { @@ -2028,7 +2334,10 @@ sub manage_reservations { my $slotheader = '<p>'. &mt('Your reservation status for any such assignments is listed below:'). '</p>'. - '<table class="LC_data_table LC_tableOfContent" id="LC_slot_reservations">'."\n"; + '<table class="LC_data_table LC_tableOfContent" id="LC_slot_reservations">'."\n". + '<tr class="LC_visually_hidden">'. + '<th>'.&mt('Resource or Folder').'</th>'. + '<th colspan="2">'.&mt('Reservation Status').'</th></tr>'."\n"; my $shownheader = 0; my $currmap; my $it=$navmap->getIterator(undef,undef,undef,1,undef,undef); @@ -2062,8 +2371,8 @@ sub manage_reservations { $arrowstate = 'closed'; } $row .= '<td>'.$spacers.'<img src="/adm/lonIcons/arrow.'.$arrowstate.'.gif" '. - 'id="arrow'.$mapnum.'" '.'alt="arrow" onmouseover="this.style.cursor=\'pointer\'" '. - 'onclick="'."toggleSlotMap('$mapnum','$rownum');".'" />'. + 'id="arrow'.$mapnum.'" '.'alt="arrow" onmouseover="this.style.cursor=\'pointer\'" tabindex="0" '. + 'onclick="'."toggleSlotMap('$mapnum','$rownum');".'" onkeydown="'."toggleSlotMap('$mapnum','$rownum');".'" />'. $icon.(' ' x6).'</td>'."\n"; if (ref($output{$currmap}) eq 'HASH') { my $formnum = $mapnum.'_'.$reservable+1; @@ -2096,6 +2405,14 @@ sub manage_reservations { $currcontainer = $parent{$depth}; } elsif (ref($resource)) { my $symb = $resource->symb(); + my $src = $resource->src(); + my ($shownsymb,$shownsrc); + $shownsymb = $resource->shown_symb(); + if ($resource->encrypted()) { + $shownsrc = &Apache::lonenc::encrypted($src); + } else { + $shownsrc = $src; + } next if (!$resource->is_problem() && !$resource->is_tool() && !$resource->is_sequence() && !$resource->is_page()); $count ++; @@ -2104,7 +2421,7 @@ sub manage_reservations { $container{$currcontainer} = $resource; $container_title{$currcontainer} = $resource->compTitle(); } - if (($resource->is_problem() || $resource->is_tool)) { + if ($resource->is_problem() || $resource->is_tool()) { next unless (exists($output{$symb})); $reservable ++; $rownum ++; @@ -2127,7 +2444,7 @@ sub manage_reservations { for (my $i=0; $i<$depth; $i++) { $r->print('<img src="'.$location.'" alt="" />'); } - $r->print('<a href="'.$resource->src().'?symb='.$symb.'">'. + $r->print('<a href="'.$shownsrc.'?symb='.$shownsymb.'">'. '<img class="LC_contentImage" src="/adm/lonIcons/'); if ($resource->is_task()) { $r->print('task.gif" alt="'.&mt('Task')); @@ -2218,7 +2535,7 @@ sub slot_chooser { } } } - next if ($exclude); + next if ($exclude); } } } @@ -2644,11 +2961,19 @@ sub display_filter { my ($formname,$cdom,$cnum,$curr,$version,$allsymbs) = @_; my $nolink = 1; my (%titles,%maptitles); - my $output = '<br /><table><tr><td valign="top">'. - '<span class="LC_nobreak"><b>'.&mt('Changes/page:').'</b><br />'. - &Apache::lonmeta::selectbox('show',$curr->{'show'},undef, - (&mt('all'),5,10,20,50,100,1000,10000)). - '</td><td> </td>'; + my $output = '<br /><table><tr><th class="LC_log_filter">'. + '<span class="LC_nobreak"><label for="show">'.&mt('Changes/page:').'</label></span></th>'. + '<th class="LC_log_filter">'.&mt('Window during which changes occurred:').'</th>'; + if (ref($allsymbs) eq 'ARRAY') { + $output.= '<th class="LC_log_filter"><label for="resource">'.&mt('Resource').'</label></th>'. + '<th class="LC_log_filter"><label for="chgcontext">'.&mt('Context').'</label></th>'; + } else { + $output.= '<th class="LC_log_filter"><label for="action">'.&mt('Action').'</label></th>'; + } + $output .= '</tr><tr><td class="LC_log_filter">'. + &Apache::lonmeta::selectbox('show',$curr->{'show'},'','show',undef, + (&mt('all'),5,10,20,50,100,1000,10000)). + '</td>'; my $startform = &Apache::lonhtmlcommon::date_setter($formname,'log_start_date', $curr->{'log_start_date'},undef, @@ -2659,13 +2984,13 @@ sub display_filter { undef,undef,undef,undef,undef,undef,$nolink); my $crstype = &Apache::loncommon::course_type(); my %lt = &reservationlog_contexts($crstype); - $output .= '<td valign="top"><b>'.&mt('Window during which changes occurred:'). - '</b><br /><table><tr><td>'.&mt('After:'). - '</td><td>'.$startform.'</td></tr><tr><td>'.&mt('Before:').'</td><td>'. - $endform.'</td></tr></table></td><td> </td>'; + $output .= '<td class="LC_log_filter"><table><tr><th>'.&mt('After:').'</th>'. + '<td>'.$startform.'</td></tr>'. + '<tr><th>'.&mt('Before:').'</th>'. + '<td>'.$endform.'</td></tr></table>'. + '</td>'; if (ref($allsymbs) eq 'ARRAY') { - $output .= '<td valign="top"><b>'.&mt('Resource').'</b><br />'. - '<select name="resource"><option value="any"'; + $output .= '<td class="LC_log_filter"><select name="resource" id="resource"><option value="any"'; if ($curr->{'resource'} eq 'any') { $output .= ' selected="selected"'; } @@ -2678,8 +3003,8 @@ sub display_filter { } $output .= ' <option value="'.$symb.'"'.$selstr.'>'.$title.'</option>'; } - $output .= '</select></td><td> </td><td valign="top"><b>'. - &mt('Context:').'</b><br /><select name="chgcontext">'; + $output .= '</select></td>'. + '<td class="LC_log_filter"><select name="chgcontext" id="chgcontext">'; foreach my $chgtype ('any','user','manage','parameter') { my $selstr = ''; if ($curr->{'chgcontext'} eq $chgtype) { @@ -2689,8 +3014,7 @@ sub display_filter { } $output .= '</select></td>'; } else { - $output .= '<td valign="top"><b>'.&mt('Action').'</b><br />'. - '<select name="action"><option value="any"'; + $output .= '<td class="LC_log_filter"><select name="action" id="action"><option value="any"'; if ($curr->{'action'} eq 'any') { $output .= ' selected="selected"'; } @@ -2704,7 +3028,7 @@ sub display_filter { } $output .= '</select></td>'; } - $output .= '<td> </td></tr></table>'. + $output .= '</tr></table>'. '<p><input type="submit" value="'. &mt('Update Display').'" /></p>'. '<p class="LC_info">'. @@ -2754,15 +3078,15 @@ sub slot_change_messaging { } sub upload_start { - my ($r)=@_; + my ($r)=@_; $r->print( &Apache::grades::checkforfile_js() - .'<h2>'.&mt('Upload a file containing the slot definitions').'</h2>' + .'<h2 class="LC_heading_2">'.&mt('Upload a file containing the slot definitions').'</h2>' .'<form method="post" enctype="multipart/form-data"' .' action="/adm/slotrequest" name="slotupload">' .'<input type="hidden" name="command" value="csvuploadmap" />' .&Apache::lonhtmlcommon::start_pick_box() - .&Apache::lonhtmlcommon::row_title(&mt('File')) + .&Apache::lonhtmlcommon::row_title('<label for="upfile">'.&mt('File').'</label>') .&Apache::loncommon::upfile_select_html() .&Apache::lonhtmlcommon::row_closure() .&Apache::lonhtmlcommon::row_title( @@ -2795,7 +3119,7 @@ sub csvuploadmap_header { $r->print( '<form method="post" enctype="multipart/form-data" action="/adm/slotrequest" name="slotupload">' - .'<h2>'.&mt('Identify fields in uploaded list').'</h2>' + .'<h2 class="LC_heading_2">'.&mt('Identify fields in uploaded list').'</h2>' .'<div class="LC_columnSection">' .&Apache::loncommon::help_open_topic( 'Slot About',&mt('Help on slots')) @@ -3072,6 +3396,9 @@ sub csv_upload_assign { '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) { @@ -3166,6 +3493,61 @@ sub slot_reservationmsg_options { return %options; } +sub get_user_breadcrumbs { + my ($symb) = @_; + my ($mapurl, $rid, $resurl) = &Apache::lonnet::decode_symb($symb); + return [] unless (&Apache::lonnet::symbverify($symb,$resurl)); + my $coursetitle = $env{'course.'.$env{'request.course.id'}.'.description'}; + my $maptitle = &Apache::lonnet::gettitle($mapurl); + my $restitle = &Apache::lonnet::gettitle($symb); + my $crstype = &Apache::loncommon::course_type(); + my ($ltiscope,$ltiuri); + my (@crumbs,@mapcrumbs); + if (($env{'request.course.id'}) && ($env{'request.lti.login'})) { + ($ltiscope,$ltiuri) = + &LONCAPA::ltiutils::lti_provider_scope($env{'request.lti.uri'}, + $env{'course.'.$env{'request.course.id'}.'.domain'}, + $env{'course.'.$env{'request.course.id'}.'.num'}); + } + if (($resurl ne '/adm/navmaps') && ($mapurl ne '') && + (!(($crstype eq 'Placement') && !$env{'request.role.adv'}))) { + unless ($ltiscope eq 'resource') { + if (($mapurl ne $env{'course.'.$env{'request.course.id'}.'.url'}) && + !(($ltiscope eq 'map') && (&Apache::lonnet::clutter($resurl) eq $ltiuri))) { + my $navmap = Apache::lonnavmaps::navmap->new(); + if (ref($navmap)) { + @mapcrumbs = $navmap->recursed_crumbs($mapurl,$restitle); + } + } + } + } + unless ((($crstype eq 'Placement') && (!$env{'request.role.adv'})) || + ($ltiscope eq 'map') || ($ltiscope eq 'resource')) { + @crumbs = ({text => $crstype.' Contents', + href => "javascript:gopost('/adm/navmaps','')"}); + } + if ($mapurl ne $env{'course.'.$env{'request.course.id'}.'.url'}) { + if (@mapcrumbs) { + push(@crumbs,@mapcrumbs); + } elsif (!(($crstype eq 'Placement') && (!$env{'request.role.adv'})) && + ($ltiscope ne 'map') && ($ltiscope ne 'resource')) { + push(@crumbs, {text => '...', + no_mt => 1}); + } + } + unless ((($crstype eq 'Placement') && (!$env{'request.role.adv'})) || (@mapcrumbs) || + (!$maptitle) || ($maptitle eq 'default.sequence') || + ($mapurl eq $env{'course.'.$env{'request.course.id'}.'.url'}) || + ($ltiscope eq 'resource')) { + push(@crumbs, {text => $maptitle, no_mt => 1, + href => &Apache::lonnet::clutter($mapurl).'?navmap=1'}); + } + if ($restitle && !@mapcrumbs) { + push(@crumbs,{text => $restitle, no_mt => 1}); + } + return \@crumbs; +} + sub handler { my $r=shift; @@ -3179,7 +3561,7 @@ sub handler { &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); my %crumb_titles = &slot_command_titles(); - my $brcrum; + my ($symb,$brcrum,$bread_crumbs_component); my $vgr=&Apache::lonnet::allowed('vgr',$env{'request.course.id'}); my $mgr=&Apache::lonnet::allowed('mgr',$env{'request.course.id'}); @@ -3204,19 +3586,30 @@ sub handler { if (ref($brcrum) eq 'ARRAY') { push(@{$brcrum},{href=>"/adm/slotrequest?command=showresv",text=>$title}); } - } elsif (($env{'form.requestattempt'}) || ($env{'form.command'} eq 'manageresv')) { + } 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}]; } + if ($env{'form.requestattempt'}) { + $symb=&unescape($env{'form.symb'}); + if ($symb =~ m{^/enc/}) { + $symb = &Apache::lonenc::unencrypted($symb); + } + if ($symb) { + $brcrum = &get_user_breadcrumbs($symb); + } + } 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'}}]; + 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'}}}); @@ -3226,25 +3619,45 @@ sub handler { } elsif ($env{'form.command'} eq 'release') { if ($env{'form.context'} eq 'usermanage') { $brcrum =[{href=>"/adm/slotrequest?command=manageresv", - text=>$crumb_titles{'showslots'}}]; + text=>$crumb_titles{'manageresv'}}]; $title = 'Manage Reservations'; if (ref($brcrum) eq 'ARRAY') { push(@{$brcrum},{href=>"/adm/slotrequest?command=$env{'form.command'}",text=>$crumb_titles{$env{'form.command'}}}); } + } elsif ($env{'form.context'} eq 'user') { + if ($env{'form.symb'}) { + $symb = &unescape($env{'form.symb'}); + if ($symb =~ m{^/enc/}) { + $symb = &Apache::lonenc::unencrypted($symb); + } + $brcrum = &get_user_breadcrumbs($symb); + } else { + $brcrum =[]; + } + } + } elsif (($env{'form.command'} eq 'get') && ($env{'form.context'} eq 'user')) { + if ($env{'form.symb'}) { + $symb=&unescape($env{'form.symb'}); + if ($symb =~ m{^/enc/}) { + $symb = &Apache::lonenc::unencrypted($symb); + } + $brcrum = &get_user_breadcrumbs($symb); + } else { + $brcrum =[]; } } else { $brcrum =[]; } - my ($symb,$js,$available,$allavailable,$got_slots); + my ($js,$available,$allavailable,$got_slots); $available = []; if ($env{'form.requestattempt'}) { - $symb=&unescape($env{'form.symb'}); @{$got_slots}=&check_for_reservation($symb,'allslots'); } if (($env{'form.requestattempt'}) || ($env{'form.command'} eq 'manageresv')) { $js = &reservation_js(\%slots,$consumed_uniqueperiods,$available,$got_slots,$symb); } - &start_page($r,$title,$brcrum,$js); + &start_page($r,$title,$brcrum,$bread_crumbs_component,$js,$mgr); + $r->print('<div class="LC_landmark" role="main">'."\n"); if ($env{'form.command'} eq 'manageresv') { $allavailable = $available; @@ -3284,7 +3697,10 @@ sub handler { } elsif (($env{'form.command'} eq 'slotlog') && ($vgr eq 'F')) { &show_reservations_log($r); } else { - my $symb=&unescape($env{'form.symb'}); + $symb = &unescape($env{'form.symb'}); + if ($symb =~ m{^/enc/}) { + $symb = &Apache::lonenc::unencrypted($symb); + } if (!defined($symb)) { &fail($r,'not_valid'); return OK; @@ -3309,9 +3725,9 @@ sub handler { return OK; } if ($env{'form.requestattempt'}) { - $r->print('<div class="LC_left_float">'); - $r->print(&show_choices($symb,undef,undef,undef,\%slots,$consumed_uniqueperiods,$available,$got_slots)); - $r->print('</div><div style="padding:0;clear:both;margin:0;border:0"></div>'); + $r->print('<div class="LC_left_float">'. + &show_choices($symb,undef,0,undef,\%slots,$consumed_uniqueperiods,$available,$got_slots). + '</div><div style="padding:0;clear:both;margin:0;border:0"></div>'); } elsif ($env{'form.command'} eq 'release') { &release_slot($r,$symb); } elsif ($env{'form.command'} eq 'get') {