--- loncom/interface/slotrequest.pm 2021/01/18 21:58:57 1.125.2.10 +++ loncom/interface/slotrequest.pm 2025/03/20 15:46:05 1.149 @@ -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.125.2.10 2021/01/18 21:58:57 raeburn Exp $ +# $Id: slotrequest.pm,v 1.149 2025/03/20 15:46:05 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -50,18 +50,18 @@ sub fail { } else { $r->print('<p>'.&mt('Failed.').'</p>'); } - + &return_link($r); &end_page($r); } sub start_page { - my ($r,$title,$brcrum,$bread_crumbs_component,$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 ($bread_crumbs_component) { + $args->{bread_crumbs_component} = $bread_crumbs_component; } } if (($env{'form.requestattempt'}) || ($env{'form.command'} eq 'manageresv')) { @@ -74,12 +74,37 @@ 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'}); + 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 { @@ -259,7 +284,104 @@ function uncheckSlotRadio() { } if (slotpicks.length) { for (var i=0; i<slotpicks.length; i++) { - slotpicks[i].checked = false; + slotpicks[i].checked = false; + } + } +} + +function toggleSlotMap(maprownum,rownum) { + if (document.getElementById('arrow'+maprownum)) { + var img = document.getElementById('arrow'+maprownum); + var rowdisplay; + var celldisplay = ''; + if (img.src.indexOf('arrow.open.gif')!=-1) { + img.src = '/adm/lonIcons/arrow.closed.gif'; + rowdisplay = 'none'; + } + else { + img.src = '/adm/lonIcons/arrow.open.gif'; + rowdisplay = 'table-row'; + celldisplay = 'none'; + } + var resrows; + var maptext; + if (document.getElementsByClassName) { + resrows = document.getElementsByClassName('LC_slotresrow_'+maprownum); + maptext = document.getElementsByClassName('LC_slotmaptext_'+maprownum); + } else { + resrows = getElementsByClassName(document.body,'LC_slotresrow_'+maprownum); + maptext = getElementsByClassName(document.body,'LC_slotmaptext_'+maprownum); + } + if (maptext.length) { + for (var i=0; i<maptext.length; i++) { + maptext[i].style.display = celldisplay; + } + } + if (resrows.length) { + var mapbgidx = 0; + var rowclasses = ['LC_even_row','LC_odd_row']; + var mapbgClass = 'LC_even_row'; + var regExpBg = /LC_odd_row/i; + if (rowdisplay == 'table-row') { + if (document.getElementById('LC_slotmaprow_'+rownum)) { + mapbgClass = document.getElementById('LC_slotmaprow_'+rownum).className; + if (regExpBg.test(mapbgClass)) { + mapbgidx = 1; + } + } + } + for (var i=0; i<resrows.length; i++) { + resrows[i].style.display = rowdisplay; + if (rowdisplay == 'table-row') { + mapbgidx ++; + var bgcolnew = mapbgidx % 2; + var bgcolold = (mapbgidx+1) % 2; + var k = i+parseInt(rownum)+1; + if (document.getElementById('LC_slotresrow_'+k)) { + document.getElementById('LC_slotresrow_'+k).className = document.getElementById('LC_slotresrow_'+k).className.replace(rowclasses[bgcolold],rowclasses[bgcolnew]); + } + } + } + if (document.getElementById('LC_slot_reservations')) { + var numrowsOdd = resrows.length % 2; + if (numrowsOdd) { + var lastbgClass = 'LC_even_row'; + var idx = 0; + var lastresnum = parseInt(rownum) + resrows.length; + if (rowdisplay == 'none') { + lastresnum = rownum; + if (document.getElementById('LC_slotmaprow_'+rownum)) { + lastbgClass = document.getElementById('LC_slotmaprow_'+rownum).className; + } + } else { + lastresnum = parseInt(rownum) + resrows.length; + if (document.getElementById('LC_slotresrow_'+lastresnum)) { + lastbgClass = document.getElementById('LC_slotresrow_'+lastresnum).className; + } + } + if (regExpBg.test(lastbgClass)) { + idx = 1; + } + var table = document.getElementById('LC_slot_reservations'); + if ((table.rows.length) && (table.rows.length >= lastresnum)) { + for (var i=lastresnum; i<table.rows.length; i++) { + if (table.rows[i].style.display != 'none') { + idx ++; + var bgcolnew = idx % 2; + var bgcolold = (idx+1) % 2; + j = i+1; + if (document.getElementById('LC_slotmaprow_'+j)) { + document.getElementById('LC_slotmaprow_'+j).className = rowclasses[bgcolnew]; + } else { + if (document.getElementById('LC_slotresrow_'+j)) { + document.getElementById('LC_slotresrow_'+j).className = document.getElementById('LC_slotresrow_'+j).className.replace(rowclasses[bgcolold],rowclasses[bgcolnew]); + } + } + } + } + } + } + } } } } @@ -290,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, @@ -335,7 +457,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) { @@ -371,7 +493,7 @@ sub get_consumed_uniqueperiods { return 'error: Unable to determine current status'; } my @problems = $navmap->retrieveResources(undef, - sub { $_[0]->is_problem() },1,0); + sub { $_[0]->is_problem() || $_[0]->is_tool() },1,0); my %used_slots; foreach my $problem (@problems) { my $symb = $problem->symb(); @@ -470,7 +592,7 @@ sub make_reservation { 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'; } @@ -496,14 +618,14 @@ 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' => $symb_for_db); @@ -582,7 +704,7 @@ sub remove_registration { sub remove_registration_user { my ($r) = @_; - + my $slot_name = $env{'form.slotname'}; my $name = &Apache::loncommon::plainname($env{'form.uname'}, @@ -592,7 +714,7 @@ 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','context']); } @@ -628,14 +750,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 @@ -679,7 +801,7 @@ sub release_slot { } 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>'); @@ -869,7 +991,7 @@ sub release_reservation { if ($passed_resource->is_map()) { my ($a_resource) = $navmap->retrieveResources($passed_resource, - sub {$_[0]->is_problem()},0,1); + sub {$_[0]->is_problem() || $_[0]->is_tool() },0,1); $parm_symb = $a_resource->symb(); } } else { @@ -965,7 +1087,7 @@ sub update_selectable { if ($passed_resource->is_map()) { my ($a_resource) = $navmap->retrieveResources($passed_resource, - sub {$_[0]->is_problem()},0,1); + 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 @@ -1041,15 +1163,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)=@_; @@ -1201,7 +1340,7 @@ sub allowed_slot { if (($slot->{'endreserve'}) && ($slot->{'endreserve'} < time)) { return 0; - } + } &Apache::lonxml::debug("$slot_name reserve good"); my $userallowed=0; @@ -1246,10 +1385,32 @@ sub allowed_slot { return 0 if (!$userallowed); # not allowed for this resource - if (defined($slot->{'symb'}) - && $slot->{'symb'} ne $symb) { - unless ((ref($toskip) eq 'HASH') && ($toskip->{'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; + } } } @@ -1278,7 +1439,7 @@ sub get_description { } sub show_choices { - my ($r,$symb,$formname,$num,$slots,$consumed_uniqueperiods,$available,$got_slots)=@_; + my ($symb,$formname,$num,$class,$slots,$consumed_uniqueperiods,$available,$got_slots)=@_; my $output; &Apache::lonxml::debug("Checking Slots"); if (!ref($available) eq 'ARRAY') { @@ -1287,11 +1448,15 @@ sub show_choices { if (!@{$available}) { $output = '<span class="LC_info">'.&mt('No available times.').'</span>'; 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>'; } - $r->print($output); - return; + if ($class) { + return '<div class="'.$class.'">'.$output.'</div>'; + } else { + return $output; + } } if (@{$available} > 1) { my $numavailable = scalar(@{$available}); @@ -1308,7 +1473,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'); @@ -1322,7 +1487,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>'. @@ -1342,7 +1507,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 = ''; @@ -1439,8 +1604,11 @@ STUFF if (@{$available} > 1) { $output .= '</div></fieldset>'; } - $r->print($output); - return; + if ($class) { + return '<div class="'.$class.'">'.$output.'</div>'; + } else { + return $output; + } } sub to_show { @@ -1502,7 +1670,7 @@ sub to_show { } return 0; } - + return 1; } @@ -1562,7 +1730,7 @@ sub show_table { ); return; } - + my %Saveable_Parameters = ('show' => 'array', 'when' => 'scalar', 'order' => 'scalar', @@ -1591,12 +1759,13 @@ sub show_table { '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'); @@ -1604,7 +1773,7 @@ sub show_table { } my @show_order=('name','description','type','starttime','endtime', 'startreserve','endreserve','reservationmsg','secret','space', - 'ip','symb','allowedsections','allowedusers','uniqueperiod', + 'ip','iptied','symb','allowedsections','allowedusers','uniqueperiod', 'scheduled','proctor'); my @show = (exists($env{'form.show'})) ? &Apache::loncommon::get_env_multiple('form.show') @@ -1651,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'; @@ -1664,48 +1833,44 @@ 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>'); $r->print('<p><input type="submit" name="start" value="'.&mt('Update Display').'" /></p>'); 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>'; + &Apache::loncommon::start_data_table_header_row().' + <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>'; @@ -1731,7 +1896,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] @@ -1765,7 +1930,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)); @@ -1807,13 +1972,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='<a href="'.$res.'?symb='.$slots{$slot}{'symb'}.'">'.$title.'</a>'; + 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,'<a href="'.$res.'?symb='.$reqsymb.'">'.$title.'</a>'); + } } my $allowedsections; @@ -1864,11 +2037,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 />'; @@ -1881,7 +2054,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') { @@ -1938,8 +2111,18 @@ LOGLINK if (exists($show{'ip'})) { $colspan++;$r->print("<td>$slots{$slot}{'ip'}</td>\n"); } + if (exists($show{'iptied'})) { + $colspan++; + if ($slots{$slot}{'iptied'} eq 'yes') { + $r->print('<td>'.&mt('Yes')."</td>\n"); + } elsif ($slots{$slot}{'iptied'} eq 'answer') { + $r->print('<td>'.&mt('Yes, including post-answer date')."</td>\n"); + } else { + $r->print('<td>'.&mt('No')."</td>\n"); + } + } if (exists($show{'symb'})) { - $colspan++;$r->print("<td>$title</td>\n"); + $colspan++;$r->print("<td>".join('<br />',@titles)."</td>\n"); } if (exists($show{'allowedsections'})) { $colspan++;$r->print("<td>$allowedsections</td>\n"); @@ -1973,6 +2156,7 @@ STUFF sub manage_reservations { my ($r,$crstype,$slots,$consumed_uniqueperiods,$allavailable) = @_; + my ($cnum,$cdom)=&get_course(); my $navmap = Apache::lonnavmaps::navmap->new(); $r->print('<p>' .&mt('Instructors may use a reservation system to place restrictions on when and where assignments can be worked on.') @@ -2004,179 +2188,236 @@ sub manage_reservations { '</span>'); return; } - my (%parent,%shownparent,%container,%container_title,%contents); - my ($depth,$count,$reservable,$lastcontainer,$rownum) = (0,0,0,0,0); - my @backgrounds = ("LC_odd_row","LC_even_row"); + my (%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='<span class="LC_nobreak">'.&mt('Reserved:'). + ' '.$slotdescription.'</span><br />'. + &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='<span class="LC_nobreak">'.&mt('Reserved:'). + ' '.$slotdescription.'</span><br />'. + &mt('Problem is currently available.'); + } elsif ($slot_status == $resource->RESERVED_LOCATION) { + $msg='<span class="LC_nobreak">'.&mt('Reserved:'). + ' '.$slotdescription.'</span><br />'. + &mt('Problem is available at a different location.'); + $get_choices = 1; + } elsif ($slot_status == $resource->RESERVED_LATER) { + $msg='<span class="LC_nobreak">'.&mt('Reserved:'). + ' '.$slotdescription.'</span><br />'. + &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 = '<p>'. &mt('Your reservation status for any such assignments is listed below:'). '</p>'. - '<table class="LC_data_table LC_tableOfContent">'."\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); while (my $resource = $it->next()) { if ($resource == $it->BEGIN_MAP()) { $depth++; - $parent{$depth} = $lastcontainer; - } - if ($resource == $it->END_MAP()) { - $depth--; - $lastcontainer = $parent{$depth}; - } - if (ref($resource)) { - my $symb = $resource->symb(); - my $ressymb = $symb; - $contents{$lastcontainer} ++; - next if (!$resource->is_problem() && !$resource->is_sequence() && - !$resource->is_page()); - $count ++; - if (($resource->is_sequence()) || ($resource->is_page())) { - $lastcontainer = $count; - $container{$lastcontainer} = $resource; - $container_title{$lastcontainer} = $resource->compTitle(); - } - if ($resource->is_problem()) { - my ($useslots) = $resource->slot_control(); - next if (($useslots eq '') || ($useslots =~ /^\s*no\s*$/i)); - my ($msg,$get_choices,$slotdescription); - my $title = $resource->compTitle(); - my $status = $resource->simpleStatus('0'); - my ($slot_status,$date,$slot_name) = $resource->check_for_slot('0'); - if ($slot_name ne '') { - my %slot=&Apache::lonnet::get_slot($slot_name); - $slotdescription=&get_description($slot_name,\%slot); - } - if ($slot_status == $resource->NOT_IN_A_SLOT) { - $msg=&mt('No current reservation.'); - $get_choices = 1; - } elsif ($slot_status == $resource->NEEDS_CHECKIN) { - $msg='<span class="LC_nobreak">'.&mt('Reserved:'). - ' '.$slotdescription.'</span><br />'. - &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='<span class="LC_nobreak">'.&mt('Reserved:'). - ' '.$slotdescription.'</span><br />'. - &mt('Problem is currently available.'); - } elsif ($slot_status == $resource->RESERVED_LOCATION) { - $msg='<span class="LC_nobreak">'.&mt('Reserved:'). - ' '.$slotdescription.'</span><br />'. - &mt('Problem is available at a different location.'); - $get_choices = 1; - } elsif ($slot_status == $resource->RESERVED_LATER) { - $msg='<span class="LC_nobreak">'.&mt('Reserved:'). - ' '.$slotdescription.'</span><br />'. - &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'); + $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; } - } - $reservable ++; - my $treelevel = $depth; - my $higherup = $lastcontainer; - if ($depth > 1) { - my @maprows; - while ($treelevel > 1) { - if (ref($container{$higherup})) { - my $res = $container{$higherup}; - last if (defined($shownparent{$higherup})); - my $maptitle = $res->compTitle(); - my $type = 'sequence'; - if ($res->is_page()) { - $type = 'page'; - } - &show_map_row($treelevel,$location,$type,$maptitle, - \@maprows); - $shownparent{$higherup} = 1; + my $bgcolor = $backgrounds[$shown % $numcolors]; + my ($spacers,$icon); + my $row = '<tr class="'.$bgcolor.'" id="LC_slotmaprow_'.$rownum.'">'; + 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'; } - $treelevel --; - $higherup = $parent{$treelevel}; - } - foreach my $item (@maprows) { - $rownum ++; - my $bgcolor = $backgrounds[$rownum % $numcolors]; - if (!$shownheader) { - $r->print($slotheader); - $shownheader = 1; + $row .= '<td>'.$spacers.'<img src="/adm/lonIcons/arrow.'.$arrowstate.'.gif" '. + 'id="arrow'.$mapnum.'" '.'alt="arrow" onmouseover="this.style.cursor=\'pointer\'" '. + 'onclick="'."toggleSlotMap('$mapnum','$rownum');".'" />'. + $icon.(' ' x6).'</td>'."\n"; + if (ref($output{$currmap}) eq 'HASH') { + my $formnum = $mapnum.'_'.$reservable+1; + my $class = 'LC_slotmaptext_'.$mapnum; + if ($output{$currmap}{'hasaction'}) { + $row .= '<td valign="top"><span class="'.$class.'">'. + $output{$currmap}{'msg'}. + '</span></td><td valign="top">'. + &slot_chooser($repsymbs{$currmap},$class,$formnum, + $allavailable,$slots,$consumed_uniqueperiods). + '</td>'; + } else { + $row .= '<td colspan="2" valign="middle"><span class="'.$class.'">'. + $output{$currmap}{'msg'}. + '</span></td>'; + } + $row .= '</tr>'."\n"; + } else { + $row .= '<td colspan="2"> </td></tr>'."\n"; } - $r->print('<tr class="'.$bgcolor.'">'.$item.'</tr>'."\n"); + } else { + my ($spacers,$icon) = &show_map_row($depth,$location,$currmaptype,$currmaptitle); + $row .= '<td>'.$spacers.$icon.(' ' x6).'</td><td colspan="2"> </td></tr>'."\n"; } + $r->print($row); } + } + } elsif ($resource == $it->END_MAP()) { + $depth--; + $currcontainer = $parent{$depth}; + } elsif (ref($resource)) { + my $symb = $resource->symb(); + next if (!$resource->is_problem() && !$resource->is_tool() && + !$resource->is_sequence() && !$resource->is_page()); + $count ++; + if (($resource->is_sequence()) || ($resource->is_page())) { + $currcontainer = $count; + $container{$currcontainer} = $resource; + $container_title{$currcontainer} = $resource->compTitle(); + } + if ($resource->is_problem() || $resource->is_tool()) { + next unless (exists($output{$symb})); + $reservable ++; $rownum ++; - my $bgcolor = $backgrounds[$rownum % $numcolors]; if (!$shownheader) { $r->print($slotheader); $shownheader = 1; } - $r->print('<tr class="'.$bgcolor.'"><td>'."\n"); + my $style; + if (exists($output{$currmap})) { + $style = 'none'; + } else { + $style = 'table-row'; + $shown ++; + } + my $title = $resource->compTitle(); + my $bgcolor = $backgrounds[$shown % $numcolors]; + $r->print('<tr class="'.$bgcolor.' LC_slotresrow_'.$mapnum.'"'. + ' style="display:'.$style.'" id="LC_slotresrow_'.$rownum.'">'. + '<td>'); for (my $i=0; $i<$depth; $i++) { $r->print('<img src="'.$location.'" alt="" />'); } - my $result = '<a href="'.$resource->src().'?symb='.$symb.'">'. - '<img class="LC_contentImage" src="/adm/lonIcons/'; + $r->print('<a href="'.$resource->src().'?symb='.$symb.'">'. + '<img class="LC_contentImage" src="/adm/lonIcons/'); if ($resource->is_task()) { - $result .= 'task.gif" alt="'.&mt('Task'); + $r->print('task.gif" alt="'.&mt('Task')); + } elsif ($resource->is_tool()) { + $r->print('unknown.gif" alt="'.&mt('External Tool')); } else { - $result .= 'problem.gif" alt="'.&mt('Problem'); - } - $result .= '" /><b>'.$title.'</b></a>'.(' ' x6).'</td>'; - my $hasaction; - if ($status == $resource->OPEN) { - if ($get_choices) { - $hasaction = 1; - } + $r->print('problem.gif" alt="'.&mt('Problem')); } - if ($hasaction) { - $result .= '<td valign="top">'.$msg.'</td>'. - '<td valign="top">'; + $r->print('" /><b>'.$title.'</b></a>'.(' ' x6).'</td>'); + my $class = 'LC_slottext_'.$mapnum; + if ($output{$symb}{'hasaction'}) { + $r->print('<td valign="top"><span class="'.$class.'">'.$output{$symb}{'msg'}.'</span></td>'. + '<td valign="top">'. + &slot_chooser($symb,$class,$reservable,$allavailable,$slots, + $consumed_uniqueperiods).'</td>'); } else { - $result .= '<td colspan="2" valign="middle">'.$msg.'</td>'; + $r->print('<td colspan="2" valign="middle">'. + '<span class="'.$class.'">'.$output{$symb}{'msg'}.'</span>'. + '</td>'); } - $r->print($result); - if ($hasaction) { - my @got_slots=&check_for_reservation($symb,'allslots'); - if ($got_slots[0] =~ /^error: /) { - $r->print('<span class="LC_error">'. - &mt('An error occurred determining slot availability.'). - '</span>'); - } else { - my $formname = 'manageres_'.$reservable; - 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 ((defined($slots->{$slot}->{'symb'})) && - ($slots->{$slot}->{'symb'} ne $symb)) { - next; - } - } - push(@available,$slot); - } - } - &show_choices($r,$symb,$formname,$reservable,$slots,$consumed_uniqueperiods, - \@available,\@got_slots); - } - } - $r->print('</td>'); - } - $r->print('</tr>'); + $r->print('</tr>'."\n"); } } } @@ -2197,19 +2438,68 @@ sub manage_reservations { } sub show_map_row { - my ($depth,$location,$type,$title,$maprows) = @_; - my $output = '<td>'; + my ($depth,$location,$type,$title) = @_; + my $spacers; for (my $i=0; $i<$depth-1; $i++) { - $output .= '<img src="'.$location.'" alt="" />'; + $spacers .= '<img src="'.$location.'" alt="" />'; } + my $icon; if ($type eq 'page') { - $output .= '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" /> '."\n"; + $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" /> '."\n"; } else { - $output .= '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" /> '."\n"; + $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" /> '."\n"; } - $output .= $title.'</td><td colspan="2"> </td>'."\n"; - unshift (@{$maprows},$output); - return; + $icon .= $title; + return ($spacers,$icon); +} + +sub slot_chooser { + my ($symb,$class,$formnum,$allavailable,$slots,$consumed_uniqueperiods) = @_; + my $output; + my @got_slots=&check_for_reservation($symb,'allslots'); + if ($got_slots[0] =~ /^error: /) { + $output = '<span class="'.$class.'"><span class="LC_error">'. + &mt('An error occurred determining slot availability.'). + '</span></span>'; + } 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 { @@ -2221,8 +2511,7 @@ sub show_reservations { $udom = $env{'user.domain'}; } my $formname = 'slotlog'; - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my ($cnum,$cdom)=&get_course(); my $crstype = &Apache::loncommon::course_type(); my %log=&Apache::lonnet::dump('nohist_'.$cdom.'_'.$cnum.'_slotlog',$udom,$uname); if ($env{'form.origin'} eq 'aboutme') { @@ -2397,8 +2686,7 @@ sub show_reservations_log { return; } my $formname = 'reservationslog'; - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my ($cnum,$cdom)=&get_course(); my %slotlog=&Apache::lonnet::dump('nohist_slotreservationslog',$cdom,$cnum); if ((keys(%slotlog))[0]=~/^error\:/) { undef(%slotlog); } @@ -2625,11 +2913,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, @@ -2640,13 +2936,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"'; } @@ -2659,8 +2955,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) { @@ -2670,8 +2966,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"'; } @@ -2685,7 +2980,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">'. @@ -2735,15 +3030,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( @@ -2776,7 +3071,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')) @@ -2933,10 +3228,11 @@ sub csvupload_fields { ['endreserve','Reservation End Time'], ['reservationmsg','Message when reservation changed'], ['ip','IP or DNS restriction'], + ['iptied','Unique IP each student'], ['proctor','List of proctor ids'], ['description','Slot Description'], ['maxspace','Maximum number of reservations'], - ['symb','Resource Restriction'], + ['symb','Resource(s)/Map(s) Restriction'], ['uniqueperiod','Date range of slot exclusion'], ['secret','Secret word proctor uses to validate'], ['allowedsections','Sections slot is restricted to'], @@ -3057,6 +3353,11 @@ sub csv_upload_assign { } } } + 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+$//; @@ -3182,7 +3483,7 @@ 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}]; @@ -3224,7 +3525,8 @@ sub handler { 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); + &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; @@ -3283,13 +3585,14 @@ 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'}) { $r->print('<div class="LC_left_float">'); - &show_choices($r,$symb,undef,undef,\%slots,$consumed_uniqueperiods,$available,$got_slots); + $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>'); } elsif ($env{'form.command'} eq 'release') { &release_slot($r,$symb);