--- loncom/interface/lonblockingmenu.pm	2015/04/15 03:28:19	1.14
+++ loncom/interface/lonblockingmenu.pm	2021/01/02 21:07:36	1.29
@@ -2,7 +2,7 @@
 # Routines for configuring blocking of access to collaborative functions, 
 # and specific resources during an exam
 #
-# $Id: lonblockingmenu.pm,v 1.14 2015/04/15 03:28:19 raeburn Exp $
+# $Id: lonblockingmenu.pm,v 1.29 2021/01/02 21:07:36 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -105,6 +105,19 @@ block (including deletion), or when a ne
 
 =over
 
+=item &get_permission()
+
+Returns information about permission user has to set/modify exam
+blocking events.
+
+Inputs: None
+
+Outputs: 2
+    $readonly - true if modification of blocking events is prohibited.
+
+    $allowed  - true if blocking events information can be shown.
+
+
 =item &get_timed_items()
 
 Provides perl data structure with information about timed interval
@@ -222,7 +235,7 @@ Side Effects: &update_released_required(
 Generates web form elements used to display, cancel, or modify 
 existing blocking events. 
 
-Inputs: 7 
+Inputs: 8 
       - $r - Apache request object
 
       - $records - Reference to hash of current blocks
@@ -238,6 +251,9 @@ Inputs: 7
 
       - $blockcount - number of existing blocking events in course
 
+      - $readonly - if true, modification not allowed.
+
+
 Output: None
 
 Side Effects: prints web form elements (in a table) for current blocks. 
@@ -302,13 +318,16 @@ Creates web form elements used to select
 items in the course for use in an exam block of type: "Triggered by 
 Activating Timer".
 
-Inputs: 7 (three required, last four optional)
+Inputs: 8 (four required, last four optional)
    - $intervals - Reference to hash of parameters for timed intervals
 
    - $parmcount - numeric ID of current block
 
    - $navmap - navmaps object
 
+   - $context - this will be "accesstimes" if called by lonaccesstimes.pm,
+                or "blocking" if called internally by lonblockingmenu.pm
+
    - $currkey - current interval (where this is a block already using
                 an interval-based trigger).  
 
@@ -323,6 +342,34 @@ Inputs: 7 (three required, last four opt
 Outputs: 1 - $intervalform - web form elements used to select a time interval
 
 
+=item &interval_details()
+
+Creates name/scope of current interval and expandable/collapsible
+showing which interval parameters apply to the current folder/resource
+
+Inputs: 6
+
+    - $item - course, map url, or resource symb
+
+    - $type - course, map, or resource
+
+    - $url  - url of item (null if item is course).
+
+    - $navmap - navmaps object
+
+    - $intervals - Reference to hash of parameters for timed intervals
+
+    - $parmcount - unique ID for current element.
+
+
+Outputs: 2
+
+   - $itemname - name/scope of interval (timer) parameter
+
+   - $iteminfo - Expandable/collapsible block showing which interval
+                 (timer) parameters affect the current folder or resource.
+
+
 =item &trigger_details_toggle()
  
 Creates link used to expand item showing information about timer for current
@@ -332,6 +379,7 @@ Inputs: 1 - $parmcount - numericID of ex
 
 Outputs: 1 - returns HTML for link to display contents of information item 
 
+
 =item &show_timer_path()
 
 Display hierarchy of names of folders/sub-folders containing the current
@@ -376,12 +424,21 @@ Output: 1 - Javascript (with <script></s
 
 =item *  for action to take -- add or modify block
 
-=item *  for display of detailed information about intervals 
-
 =back
 
 
-=back  
+=item &details_javascript()
+
+Create Javascript to toggle visibility of unordered list item
+containing details about item with timed interval parameter.
+
+Inputs: none
+
+Output: 1 Javascript (with <script></script> tags) for functions used to:
+          toggle visibility of unordered list for display of detailed
+          information about intervals.
+
+=back
 
 =cut
 
@@ -422,11 +479,10 @@ sub handler {
 
 # ----------------------------------------------------------- Permissions check
 
-    unless ((&Apache::lonnet::allowed('dcm',$env{'request.course.id'})) ||
-            (&Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
-                                      '/'.$env{'request.course.sec'}))) {
+    my ($readonly,$allowed) = &get_permission();
+    unless ($allowed) {
         $env{'user.error.msg'}=
-     "/adm/setblock:dcm:0:0:Cannot set blocking of communications in a course";
+     "/adm/setblock:dcm:0:0:Cannot view/set blocking of communications in a course";
         return HTTP_NOT_ACCEPTABLE;
     }
 
@@ -471,7 +527,7 @@ sub handler {
             $r->print(&Apache::loncourserespicker::create_picker($navmap,
                                      'examblock','resourceblocks',$crstype,
                                      \%blockedmaps,\%blockedresources,
-                                     $env{'form.block'}));
+                                     $env{'form.block'},'','',undef,undef,$readonly));
         } else {
             $r->print($errormsg);
         }
@@ -480,10 +536,12 @@ sub handler {
 
 # -------------------------- Store changes and retrieve latest block information
     my $storeresult;
-    if ($env{'form.action'} eq 'store') {
-        (my $numchanges,$storeresult) = &blockstore($r,$crstype,$blockcount,\%records);
-        if ($numchanges > 0) {
-            $blockcount = &get_blockdates(\%records);
+    unless ($readonly) {
+        if ($env{'form.action'} eq 'store') {
+            (my $numchanges,$storeresult) = &blockstore($r,$crstype,$blockcount,\%records);
+            if ($numchanges > 0) {
+                $blockcount = &get_blockdates(\%records);
+            }
         }
     }
 
@@ -503,7 +561,8 @@ sub handler {
         ({href=>'/adm/setblock',
           text=>'Blocking communication/content access'});
 
-    my $js = &blockingmenu_javascript($blockcount);
+    my $js = &blockingmenu_javascript($blockcount).
+             &details_javascript();
 
     $r->print(
         &Apache::loncommon::start_page('Blocking communication/content access',$js).
@@ -519,6 +578,7 @@ sub handler {
     my %lt=&Apache::lonlocal::texthash (
             'cbds' => 'Blocking communication and/or content access during exams',
             'prev' => "For the duration of an exam, or a timed quiz, students in this course can be prevented from:",
+            'flow' => "For the duration of an exam, or a timed quiz, event-driven interruptions to a student's workflow can be suppressed:",
             'blca' => "Blocks can potentially interrupt legitimate communication between $usertype who are also both enrolled in a different LON-CAPA $lctype.",
             'pobl' => "Portfolio blocking can impact a student's ability to complete assignments in courses besides your own. Please use this feature wisely.",
             'actt' => "Action to take:",
@@ -558,9 +618,17 @@ sub handler {
             '<ul>'."\n".
             '<li>'.&mt("displaying LON-CAPA messages sent by other $usertype in the $lctype").'</li>'."\n".
             '<li>'.&mt("displaying or posting to LON-CAPA discussion boards or live chat in the $lctype").'</li>'."\n".
-            '<li>'.&mt('accessing content in LON-CAPA portfolios or blogs').'</li>'."\n".
+            '<li>'.&mt('accessing content in LON-CAPA portfolios, blogs, or user information pages').'</li>'."\n".
             '<li>'.&mt("generating printouts of $lctype content").'</li>'.
+            '<li>'.&mt("displaying the LON-CAPA gradebook in the $lctype").'</li>'.
+            '<li>'.&mt("searching $lctype content by keyword").'</li>'.  
             '<li>'.&mt("accessing $lctype content in specified folders or resources").'</li>'.
+            '<li>'.&mt("changing user's own password").'</li>'.
+            '</ul>'.
+            $lt{'flow'}.
+            '<ul>'."\n".
+            '<li>'.&mt("re-initialization of cached course structure, when a change has been made to $lctype content by a Coordinator").'</li>'.
+            '<li>'.&mt('display of Critical Messages when navigation arrows used to move to the adjacent resource').'</li>'.
             '</ul>'.
             '<p class="LC_warning">'.$lt{'blca'}.'<br />'.$lt{'pobl'}.'</p>'
         );
@@ -568,8 +636,10 @@ sub handler {
 
 # ------------------------ Choose between modifying existing block or adding new
     $r->print('<form name="blockform" method="post" action="/adm/setblock?action=store">');
-    if ($blockcount > 0) {
-         $r->print(<<"END");
+
+    unless ($readonly) {
+        if ($blockcount > 0) {
+            $r->print(<<"END");
 <div class="LC_left_float">
 <fieldset><legend>$lt{'actt'}</legend>
 <span class="LC_nobreak">
@@ -586,33 +656,61 @@ onclick="toggleAddModify();" />$lt{'addn
 <br clear="all" />
 <div id="showadd" style="display:none">
 END
-    } else {
-        $r->print($lt{'ncbc'}.'<br /><br />'.
-                  '<h4>'.$lt{'addn'}.'</h4>'.
-                  '<input type="hidden" name="blockaction" value="add" />');
+        } else {
+            $r->print($lt{'ncbc'}.'<br /><br />'.
+                      '<h4>'.$lt{'addn'}.'</h4>'.
+                      '<input type="hidden" name="blockaction" value="add" />');
+        }
     }
     my ($navmap,$errormsg) =
         &Apache::loncourserespicker::get_navmap_object($crstype,'examblock');
 
 # --------------------------------------------- Interface for adding a new block
-    &display_addblocker_table($r,$blockcount,\%ltext,\%intervals,
-                              $navmap,$errormsg);
-
-# ------------------------------------------------- Interface for existig blocks
-    if ($blockcount > 0) {
-        $r->print('</div>');
+    unless ($readonly) {
+        &display_addblocker_table($r,$blockcount,\%ltext,\%intervals,
+                                  $navmap,$errormsg);
+        if ($blockcount > 0) {
+            $r->print('</div>');
+        }
+    }
+# ------------------------------------------------ Interface for existing blocks
+    if (!$blockcount) {
+        if ($readonly) {
+            $r->print($lt{'ncbc'}.'<br />');
+        }
+    } else {
         &display_blocker_status($r,\%records,\%ltext,\%intervals,
-                                $navmap,$errormsg,$blockcount);
+                                $navmap,$errormsg,$blockcount,$readonly);
     }
-    $r->print(<<"END");
+    unless ($readonly) {
+        $r->print(<<"END");
 <br />
 <input type ="submit" value="$lt{'stor'}" />
-</form>
 END
-    $r->print(&Apache::loncommon::end_page());
+    }
+    $r->print('</form>'.
+              &Apache::loncommon::end_page());
     return OK;
 }
 
+sub get_permission {
+    my %permission;
+    my $allowed = 0;
+    my $readonly = 0;
+    return ($readonly,$allowed) unless ($env{'request.course.id'});
+    if ((&Apache::lonnet::allowed('dcm',$env{'request.course.id'})) ||
+        (&Apache::lonnet::allowed('dcm',$env{'request.course.id'}.'/'.
+                  $env{'request.course.sec'}))) {
+        $allowed = 1;
+    } elsif ((&Apache::lonnet::allowed('vcb',$env{'request.course.id'})) ||
+             (&Apache::lonnet::allowed('vcb',$env{'request.course.id'}.'/'.
+                  $env{'request.course.sec'}))) {
+        $readonly = 1;
+        $allowed = 1;
+    }
+    return ($readonly,$allowed);
+}
+
 sub get_timed_items {
     my ($cdom,$cnum) = @_;
     my ($cid,%intervals);
@@ -629,7 +727,7 @@ sub get_timed_items {
     my $resourcedata=&Apache::lonparmset::readdata($cnum,$cdom);
     if (ref($resourcedata) eq 'HASH') {
         foreach my $key (keys(%{$resourcedata})) {
-            if ($key =~ /^\Q$cid\E(.+)\.0\.interval$/) {
+            if ($key =~ /^\Q$cid\E(.*)\.0\.interval$/) {
                 my $middle = $1;
                 if ($middle eq '') {
                     $intervals{'course'}{'all'} = $resourcedata->{$key};
@@ -787,6 +885,24 @@ sub blockstore {
                                            &escape($env{'form.title_'.$key})).'<br />';
                         }
                     }
+                    if ($blocktypes->{'alert'} eq 'on') {
+                        ($status,$needsrelease) = &check_release_required('alert',$chomemajor,$chomeminor);
+                        if ($status eq 'fail') {
+                            $blocktypes->{'alert'} = 'off';
+                            $output .= '<p class="LC_warning">'.
+                                       &mt('Message Alert blocking not allowed for [_1]',
+                                           &escape($env{'form.title_'.$key})).'<br />';
+                        }
+                    }
+                    if ($blocktypes->{'reinit'} eq 'on') {
+                        ($status,$needsrelease) = &check_release_required('reinit',$chomemajor,$chomeminor);
+                        if ($status eq 'fail') {
+                            $blocktypes->{'reinit'} = 'off';
+                            $output .= '<p class="LC_warning">'.
+                                       &mt('Course Re-initialization blocking not allowed for [_1]',
+                                           &escape($env{'form.title_'.$key})).'<br />';
+                        }
+                    }
                 }
                 if ($blockdocs) {
                     ($status,$needsrelease) = &check_release_required('docs',$chomemajor,$chomeminor);
@@ -974,9 +1090,9 @@ sub check_release_required {
 }
 
 sub display_blocker_status {
-    my ($r,$records,$ltext,$intervals,$navmap,$errormsg,$blockcount) = @_;
+    my ($r,$records,$ltext,$intervals,$navmap,$errormsg,$blockcount,$readonly) = @_;
     my $parmcount = 0;
-    my (%map_url,%resource_symb,%titles,%lookups);
+    my (%map_url,%resource_symb,%titles,%lookups,$disabled);
     &Apache::loncourserespicker::enumerate_course_contents($navmap,\%map_url,\%resource_symb,\%titles,'examblock');
     %{$lookups{'maps'}} = reverse(%map_url);
     %{$lookups{'resources'}} = reverse(%resource_symb);
@@ -986,10 +1102,13 @@ sub display_blocker_status {
         'noch' => 'No change',
     );
     $r->print('<div id="showmodify" style="display:block">'.
-              &Apache::loncommon::start_data_table());
+              &Apache::loncommon::start_data_table().'<tr>');
+    if ($readonly) {
+        $disabled = ' disabled="disabled"';
+    } else {
+        $r->print('<th></th>');
+    }
     $r->print(<<"END");
-  <tr>
-    <th></th>
     <th>$ltext->{'type'}</th>
     <th>$ltext->{'even'}</th>
     <th>$ltext->{'blck'}</th>
@@ -1008,8 +1127,12 @@ END
            &Apache::loncommon::aboutmewrapper(
                            &Apache::loncommon::plainname($setuname,$setudom),
                            $setuname,$setudom);
+        my $state = '';
         $r->print(&Apache::loncommon::start_data_table_row());
-        $r->print(<<"ACT");
+        if ($readonly) {
+            $state = 'disabled';
+        } else {
+            $r->print(<<"ACT");
 
         <td valign="middle"><span class="LC_nobreak"><label>
         <input type="radio" name="action_$parmcount" value="modify" />$lt{'modi'}
@@ -1023,19 +1146,21 @@ END
         </label></span>
         </td>
 ACT
+        }
         my ($start,$end,$startform,$endform); 
         if ($record =~ /^(\d+)____(\d+)$/) {
             ($start,$end) = split(/____/,$record);
             $startform = &Apache::lonhtmlcommon::date_setter('blockform','startdate_'.
-                                                             $parmcount,$start,$onchange);
+                                                             $parmcount,$start,$onchange,
+                                                             undef,$state);
             $endform = &Apache::lonhtmlcommon::date_setter('blockform','enddate_'.
-                                                           $parmcount,$end,$onchange);
+                                                           $parmcount,$end,$onchange,
+                                                           undef,$state);
             $r->print('<td><fieldset><legend>'.$ltext->{'defs'}.'</legend>'.
                       $ltext->{'star'}.':&nbsp;'.$startform.'<br />'.
                       $ltext->{'endd'}.':&nbsp;&nbsp;'.$endform.'</fieldset></td>');
         } elsif ($record =~ /^firstaccess____(.+)$/) {
             my $item = $1;
-            my ($itemname,$iteminfo,$skipdetails);
             my $type = 'map';
             my $url;
             if ($item eq 'course') {
@@ -1047,130 +1172,20 @@ ACT
                 $url = $item;
             }
             $r->print('<td><fieldset><legend>'.$ltext->{'trig'}.'</legend>');
-            if ($type eq 'course') {
-                $itemname = &mt('Timer for all items in course.');
-            } else {
-                if (&Apache::lonnet::is_on_map($url)) { 
-                    if ($type eq 'map') {
-                        if (ref($navmap)) {
-                            my $title;
-                            my $resobj = $navmap->getResourceByUrl($item);
-                            if (ref($resobj)) { 
-                                $title = $resobj->compTitle();
-                            } else {
-                                $title = &Apache::lonnet::gettitle($item);
-                            }
-                            $itemname = &mt('Timer for all items in folder: [_1]',
-                                            '<span style="font-style:italic">'.
-                                            $title.'</span>');
-                        }
-                    } else {
-                        if (ref($navmap)) {
-                            my $title;
-                            my $resobj = $navmap->getBySymb($item);
-                            if (ref($resobj)) {
-                                $title = $resobj->compTitle();
-                            } else {
-                                $title = &Apache::lonnet::gettitle($item);
-                            }
-                            $itemname = &mt('Timer for resource: [_1]',
-                                             '<span style="font-style:italic">'.
-                                             $title.'</span>');
-                        }
-                    }
-                    if (ref($navmap)) {
-                        my $path = &show_timer_path($type,$item);
-                        if ($path) {
-                            $iteminfo  = ' <span style="font-size:90%;">'.
-                                         &mt('(in: [_1])',$path).
-                                         '</span>';
-                        }
-                    }
-                } else {
-                    $skipdetails = 1;
-                    $itemname = '<span style="LC_warning">'.
-                                &mt('Timer folder/resource not in course').
-                                '</span>';  
-                }
-            }
-            if ((!$skipdetails) && (ref($intervals) eq 'HASH')) {
-                if (ref($intervals->{$type}) eq 'HASH') {
-                    $iteminfo .= &trigger_details_toggle($parmcount).
-                                '<ul id="trigdetails_'.$parmcount.'" style="display:none">';
-                    if ($type eq 'course') {
-                        foreach my $scope (keys(%{$intervals->{$type}})) {
-                            if ($scope eq 'all') {
-                                $iteminfo .= '<li>'.&mt('All users -- time limit: [_1]',
-                                         &convlim($intervals->{$type}->{$scope})).'</li>';
-                            } elsif ($scope eq 'secgrp') {
-                                if (ref($intervals->{$type}->{$scope}) eq 'HASH') {
-                                    $iteminfo .= '<li>'.&mt('Sections/groups').'<ul>';
-                                    foreach my $item (sort(keys(%{$intervals->{$type}->{$scope}}))) {
-                                        $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$item,
-                                                     &convlim($intervals->{$type}->{$scope}->{$item})).
-                                                     '</li>';
-                                    }
-                                    $iteminfo .= '</ul></li>';
-                                }
-                            } elsif ($scope eq 'users') {
-                                if (ref($intervals->{$type}->{$scope}) eq 'HASH') {
-                                    $iteminfo .= '<li>'.&mt('Users').'<ul>'; 
-                                    foreach my $item (sort(keys(%{$intervals->{$type}->{$scope}}))) {
-                                        $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',
-                                                     &convlim($item,$intervals->{$type}->{$scope}->{$item})).
-                                                     '</li>';
-                                    }
-                                    $iteminfo .= '</ul></li>';
-                                }
-                            }
-                        }
-                    } elsif (($type eq 'map') || ($type eq 'resource')) {
-                        if (ref($intervals->{$type}->{$item}) eq 'HASH') { 
-                            foreach my $scope (keys(%{$intervals->{$type}->{$item}})) {
-                                if ($scope eq 'all') {
-                                    $iteminfo .= '<li>'.&mt('All users -- time limit: [_1]',
-                                                  &convlim($intervals->{$type}->{$item}->{$scope})).
-                                                  '</li>';
-                                } elsif ($scope eq 'secgrp') {
-                                    if (ref($intervals->{$type}->{$item}->{$scope}) eq 'HASH') {
-                                        $iteminfo .= '<li>'.&mt('Sections/groups').'<ul>';
-                                        foreach my $sec (sort(keys(%{$intervals->{$type}->{$item}->{$scope}}))) {
-                                            $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$sec,
-                                                         &convlim($intervals->{$type}->{$item}->{$scope}->{$sec})).
-                                                         '</li>';
-                                        }
-                                        $iteminfo .= '</ul></li>'; 
-                                    }
-                                } elsif ($scope eq 'users') {
-                                    if (ref($intervals->{$type}->{$item}->{$scope}) eq 'HASH') {
-                                        $iteminfo .= '<li>'.&mt('Users').'<ul>';
-                                        foreach my $user (sort(keys(%{$intervals->{$type}->{$item}->{$scope}}))) {
-                                            $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$user,
-                                                         &convlim($intervals->{$type}->{$item}->{$scope}->{$user})).
-                                                         '</li>';
-                                        }
-                                        $iteminfo .= '</ul></li>';
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    $iteminfo .= '</ul>';
-                }
-            }
-            $r->print(&create_interval_form($intervals,$parmcount,$navmap,$item,$jschg,
-                                            $itemname,$iteminfo).'</fieldset></td>');
+            my ($itemname,$iteminfo) = &interval_details($item,$type,$url,$navmap,$intervals,$parmcount);
+            $r->print(&create_interval_form($intervals,$parmcount,$navmap,'blocking',$item,$jschg,
+                                            $itemname,$iteminfo,$disabled).'</fieldset></td>');
         }
         $r->print(<<"END");
         <td>
-         <input type="text" name="title_$parmcount" size="15" value="$title" onfocus="$jschg" />
+         <input type="text" name="title_$parmcount" size="15" value="$title" onfocus="$jschg" $disabled />
          <input type="hidden" name="key_$parmcount" value="$blockid" />
          <br />
          <br />
          $ltext->{'setb'}: $settername
         </td>
 END
-        $r->print('<td>'.&blocker_checkboxes($parmcount,$blocks,$jschg,\%lookups).'</td>'.
+        $r->print('<td>'.&blocker_checkboxes($parmcount,$blocks,$jschg,\%lookups,$disabled).'</td>'.
                   &Apache::loncommon::end_data_table_row());
         $parmcount++;
     }
@@ -1222,7 +1237,7 @@ sub display_addblocker_table {
     my %lt = &Apache::lonlocal::texthash(
         'exam' => 'e.g., Exam 1',
     );
-    my $intervalform = &create_interval_form($intervals,$parmcount,$navmap);
+    my $intervalform = &create_interval_form($intervals,$parmcount,$navmap,'blocking');
     if ($intervalform ne '') {
         $intervalform = '<fieldset>'.
                         '<legend>'.$ltext->{'chtr'}.'</legend>'.
@@ -1260,7 +1275,7 @@ END
 }
 
 sub blocker_checkboxes {
-    my ($parmcount,$blocks,$jschg,$lookups) = @_;
+    my ($parmcount,$blocks,$jschg,$lookups,$disabled) = @_;
     my ($typeorder,$types) = &blocktype_text();
     my $numinrow = 2;
     my %currdocs;
@@ -1327,7 +1342,7 @@ sub blocker_checkboxes {
         } 
         $output .= '<span class="LC_nobreak"><label>'."\n".
                    '<input type="checkbox" id="'.$item.'" name="'.$item.'"'.
-                   $blockstatus.$clickaction.' value="1" />'.
+                   $blockstatus.$clickaction.' value="1"'.$disabled.' />'.
                    $types->{$block}.'</label></span>'."\n";
         if ($block eq 'docs') {
             if ($blockstatus ne '') {
@@ -1346,9 +1361,10 @@ sub blocker_checkboxes {
 }
 
 sub create_interval_form {
-    my ($intervals,$parmcount,$navmap,$currkey,$jschg,$itemname,$iteminfo) = @_;
+    my ($intervals,$parmcount,$navmap,$context,$currkey,$jschg,$itemname,$iteminfo,$disabled) = @_;
     return unless ((ref($intervals) eq 'HASH') && (ref($navmap)));
     my $intervalform;
+    my $counter = 0;
     if (keys(%{$intervals}) > 0) {
         foreach my $type (sort(keys(%{$intervals}))) {
             if ($type eq 'course') {
@@ -1359,7 +1375,7 @@ sub create_interval_form {
                     $clickaction = ' onclick="'.$jschg.'"';
                 }
                 $intervalform .= '<label><input type="radio" name="firstaccess_'.$parmcount.
-                                 '" value="course"'.$checked.$clickaction.' />';
+                                 '" value="course"'.$checked.$clickaction.$disabled.' />';
                 if ($currkey eq 'course') {
                     $intervalform .= $itemname;
                 } else {
@@ -1368,8 +1384,14 @@ sub create_interval_form {
                 $intervalform .= '</label>';
                 if ($currkey eq 'course') {
                     $intervalform .= $iteminfo;
+                } elsif ($context eq 'accesstimes') {
+                    (undef,$iteminfo) = &interval_details('course',$type,'',$navmap,$intervals,$counter);
+                    if ($iteminfo) {
+                        $intervalform .= ' '.$iteminfo;
+                    }
                 }
                 $intervalform .= '<br />';
+                $counter ++;
             } elsif ($type eq 'map') {
                 if (ref($intervals->{$type}) eq 'HASH') {
                     if (ref($navmap)) {
@@ -1384,7 +1406,7 @@ sub create_interval_form {
                             }
                             $intervalform .= '<label><input type="radio" name="firstaccess_'.$parmcount.
                                              '" value="'.&HTML::Entities::encode($map,'"<>&').'"'.
-                                             $checked.$clickaction.' />';
+                                             $checked.$clickaction.$disabled.' />';
                             if ($currkey eq $map) {
                                 $intervalform .= $itemname.'</label>'.$iteminfo;
                             } else {
@@ -1404,8 +1426,15 @@ sub create_interval_form {
                                 $intervalform .= &mt('Timer for all items in folder: [_1]',
                                                      '<i>'.$title.'</i>').
                                                  '</label>'.$path;
+                                if ($context eq 'accesstimes') {
+                                    (undef,$iteminfo) = &interval_details($map,$type,$map,$navmap,$intervals,$counter);
+                                    if ($iteminfo) {
+                                        $intervalform .= ' '.$iteminfo;
+                                    }
+                                }
                             }
                             $intervalform .= '<br />';
+                            $counter ++;
                         }
                     }
                 }
@@ -1425,14 +1454,15 @@ sub create_interval_form {
                             }
                             $intervalform .= '<label><input type="radio" name="firstaccess_'.$parmcount.
                                              '" value="'.&HTML::Entities::encode($resource,'"<>&').'"'.
-                                             $checked.$clickaction.' />';
+                                             $checked.$clickaction.$disabled.' />';
                             if ($currkey eq $resource) {
                                 $intervalform .= $itemname.'</label>'.$iteminfo;
                             } else {
                                 my ($title,$path,$hierarchy);
                                 if (ref($resobj)) {
                                     $title = $resobj->compTitle();
-                                } else {
+                                }
+                                if ($title eq '') {
                                     $title = &Apache::lonnet::gettitle($resource);
                                 }
                                 $hierarchy = &show_timer_path($type,$resource,$navmap);
@@ -1444,8 +1474,19 @@ sub create_interval_form {
                                 $intervalform .= &mt('Timer for resource: [_1]','<i>'.$title.'</i>').
                                                  '</label>'.
                                                  $path;
+                                if ($context eq 'accesstimes') {
+                                    if (ref($resobj)) {
+                                        my $url = $resobj->src();
+                                        if ($url eq '') {
+                                            (my $map, my $resid, $url) = &Apache::lonnet::decode_symb($resource);
+                                        }
+                                        ($itemname,$iteminfo) = &interval_details($resource,$type,$url,$navmap,$intervals,$counter);
+                                        $intervalform .= ' '.$iteminfo;
+                                    }
+                                }
                             }
                             $intervalform .= '<br />';
+                            $counter ++;
                         }
                     }
                 }
@@ -1455,7 +1496,7 @@ sub create_interval_form {
         if ($currkey ne '') {
             $intervalform = '<input type="radio" name="firstaccess_'.$parmcount.
                             '" checked="checked" value="'.
-                            &HTML::Entities::encode($currkey,'"<>&').' />'.
+                            &HTML::Entities::encode($currkey,'"<>&').'"'.$disabled.' />'.
                             $itemname.'<br />';
         } else {
             $intervalform = &mt('No timed items defined.').' '.
@@ -1473,6 +1514,121 @@ sub trigger_details_toggle {
            'style="text-decoration: none;"><b>'.&mt('(More ...)').'</b></a></span>';
 }
 
+sub interval_details {
+    my ($item,$type,$url,$navmap,$intervals,$parmcount) = @_;
+    my ($itemname,$iteminfo,$skipdetails);
+    if ($type eq 'course') {
+        $itemname = &mt('Timer for all items in course.');
+    } else {
+        if (&Apache::lonnet::is_on_map($url)) {
+            if ($type eq 'map') {
+                if (ref($navmap)) {
+                    my $title;
+                    my $resobj = $navmap->getResourceByUrl($item);
+                    if (ref($resobj)) {
+                        $title = $resobj->compTitle();
+                    } else {
+                        $title = &Apache::lonnet::gettitle($item);
+                    }
+                    $itemname = &mt('Timer for all items in folder: [_1]',
+                                    '<span style="font-style:italic">'.
+                                    $title.'</span>');
+                }
+            } else {
+                if (ref($navmap)) {
+                    my $title;
+                    my $resobj = $navmap->getBySymb($item);
+                    if (ref($resobj)) {
+                        $title = $resobj->compTitle();
+                    } else {
+                        $title = &Apache::lonnet::gettitle($item);
+                    }
+                    $itemname = &mt('Timer for resource: [_1]',
+                                    '<span style="font-style:italic">'.
+                                    $title.'</span>');
+                }
+            }
+            if (ref($navmap)) {
+                my $path = &show_timer_path($type,$item);
+                if ($path) {
+                   $iteminfo  = ' <span style="font-size:90%;">'.
+                                  &mt('(in: [_1])',$path).
+                                  '</span>';
+                }
+            }
+        } else {
+            $skipdetails = 1;
+            $itemname = '<span style="LC_warning">'.
+                        &mt('Timer folder/resource not in course').
+                        '</span>';
+        }
+    }
+    if ((!$skipdetails) && (ref($intervals) eq 'HASH') && (ref($intervals->{$type}) eq 'HASH')) {
+        $iteminfo = &trigger_details_toggle($parmcount).
+                    '<ul id="trigdetails_'.$parmcount.'" style="display:none">';
+        if ($type eq 'course') {
+            foreach my $scope (keys(%{$intervals->{$type}})) {
+                if ($scope eq 'all') {
+                    $iteminfo .= '<li>'.&mt('All users -- time limit: [_1]',
+                                 &convlim($intervals->{$type}->{$scope})).'</li>';
+                } elsif ($scope eq 'secgrp') {
+                    if (ref($intervals->{$type}->{$scope}) eq 'HASH') {
+                        $iteminfo .= '<li>'.&mt('Sections/groups').'<ul>';
+                        foreach my $item (sort(keys(%{$intervals->{$type}->{$scope}}))) {
+                            $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$item,
+                                         &convlim($intervals->{$type}->{$scope}->{$item})).
+                                         '</li>';
+                        }
+                        $iteminfo .= '</ul></li>';
+                    }
+                } elsif ($scope eq 'users') {
+                    if (ref($intervals->{$type}->{$scope}) eq 'HASH') {
+                        $iteminfo .= '<li>'.&mt('Users').'<ul>';
+                        foreach my $item (sort(keys(%{$intervals->{$type}->{$scope}}))) {
+                            $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',
+                                         &convlim($item,$intervals->{$type}->{$scope}->{$item})).
+                                         '</li>';
+                        }
+                        $iteminfo .= '</ul></li>';
+                    }
+                }
+            }
+        } elsif (($type eq 'map') || ($type eq 'resource')) {
+            if (ref($intervals->{$type}->{$item}) eq 'HASH') {
+                foreach my $scope (keys(%{$intervals->{$type}->{$item}})) {
+                    if ($scope eq 'all') {
+                        $iteminfo .= '<li>'.&mt('All users -- time limit: [_1]',
+                                     &convlim($intervals->{$type}->{$item}->{$scope})).
+                                     '</li>';
+                    } elsif ($scope eq 'secgrp') {
+                        if (ref($intervals->{$type}->{$item}->{$scope}) eq 'HASH') {
+                            $iteminfo .= '<li>'.&mt('Sections/groups').'<ul>';
+                            foreach my $sec (sort(keys(%{$intervals->{$type}->{$item}->{$scope}}))) {
+                                $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$sec,
+                                             &convlim($intervals->{$type}->{$item}->{$scope}->{$sec})).
+                                            '</li>';
+                            }
+                            $iteminfo .= '</ul></li>';
+                        }
+                    } elsif ($scope eq 'users') {
+                        if (ref($intervals->{$type}->{$item}->{$scope}) eq 'HASH') {
+                            $iteminfo .= '<li>'.&mt('Users').'<ul>';
+                            foreach my $user (sort(keys(%{$intervals->{$type}->{$item}->{$scope}}))) {
+                                $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$user,
+                                             &convlim($intervals->{$type}->{$item}->{$scope}->{$user})).
+                                             '</li>';
+                            }
+                            $iteminfo .= '</ul></li>';
+                        }
+                    }
+                }
+            }
+        }
+        $iteminfo .= '</ul>';
+    }
+    return ($itemname,$iteminfo);
+}
+
 sub show_timer_path {
     my ($type,$item,$navmap) = @_;
     return unless(ref($navmap));
@@ -1499,19 +1655,21 @@ sub blocktype_text {
         'port' => 'Portfolio',
         'groups' => 'Groups',
         'blogs' => 'Blogs',
+        'about' => 'User Information',
         'docs' => 'Content',
         'printout' => 'Printouts',
+        'passwd' => 'Change Password',
+        'grades' => 'Gradebook',
+        'search' => 'Content Search',
+        'alert'  => 'Critical Alert',
+        'reinit' => 'Course Re-init',
     );
-    my $typeorder = ['com','chat','boards','port','groups','blogs','printout','docs'];
+    my $typeorder = ['com','chat','boards','port','groups','blogs','about','printout','docs','grades','search','alert','reinit','passwd'];
     return ($typeorder,\%types);
 }
 
 sub blockingmenu_javascript {
     my ($blockcount) = @_;
-    my %lt = &Apache::lonlocal::texthash (
-                                           more => 'More ...',
-                                           less => 'Less ...',
-                                         );
     return <<ENDSCRIPT;
 <script type="text/javascript">
 // <![CDATA[
@@ -1567,6 +1725,22 @@ function toggleAddModify() {
     return;
 }
 
+// ]]>
+</script>
+ENDSCRIPT
+
+}
+
+sub details_javascript {
+    my %lt = &Apache::lonlocal::texthash (
+                                           more => 'More ...',
+                                           less => 'Less ...',
+                                         );
+    return <<ENDSCRIPT;
+
+<script type="text/javascript">
+// <![CDATA[
+
 function showTriggerDetails(item) {
     document.getElementById('trigdetails_'+item).style.display='block';
     document.getElementById('trigdetails_'+item).style.textAlign='left';