Diff for /loncom/interface/lonwhatsnew.pm between versions 1.18 and 1.95

version 1.18, 2005/06/06 22:39:59 version 1.95, 2009/10/26 22:30:50
Line 36  use Apache::lonlocal; Line 36  use Apache::lonlocal;
 use Apache::loncoursedata();  use Apache::loncoursedata();
 use Apache::lonnavmaps();  use Apache::lonnavmaps();
 use Apache::lonuserstate;  use Apache::lonuserstate;
   use Apache::lonuserutils; 
 use Apache::Constants qw(:common :http);  use Apache::Constants qw(:common :http);
 use Time::Local;  use Time::Local;
   use GDBM_File;
   use lib '/home/httpd/lib/perl/';
   use LONCAPA;
   
 #----------------------------  #----------------------------
 # handler  # handler
Line 51  sub handler { Line 55  sub handler {
         $r->send_http_header;          $r->send_http_header;
         return OK;          return OK;
     }      }
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['command']);      &Apache::loncommon::get_unprocessed_cgi(
                                      $ENV{'QUERY_STRING'},['command','refpage']);
   
     my $command;      my $command = $env{'form.command'};
     if ($env{'form.action'} eq 'reset') {      my $refpage = $env{'form.refpage'};
         $command = 'reset';  
     } elsif ($env{'form.action'} eq 'update') {      my %checkallowed = ( coursenormalmail => 1,
         $command = 'update';   coursecritmail => 1, );
     } else {      foreach my $perm_check (['whn','whatsnew',1],
         $command = $env{'form.command'};      ['pch','coursediscussion',1],
       ['mgr','handgrading',1],
       ['vgr','abovethreshold',1],
       ['opa','haserrors',1],
       ['mdc','versionchanges',0],
                               ['vcl','newroles',1],
                               ['vcl','oldroles',1],
       ) {
    my ($perm,$key,$check_section) = @{ $perm_check };
    my $scope = $env{'request.course.id'};
    if (!($checkallowed{$key} = &Apache::lonnet::allowed($perm,$scope))) {
       $scope .= '/'.$env{'request.course.sec'};
       if ( $check_section ) {
    $checkallowed{$key} = &Apache::lonnet::allowed($perm,$scope);
       }
       if ($checkallowed{$key}) {
    $checkallowed{$key.'_section'} = $env{'request.course.sec'};
       }
    }
     }      }
   
     &Apache::loncommon::content_type($r,'text/html');      if ( ! $env{'request.course.fn'} || ! $checkallowed{'whatsnew'}) {
     $r->send_http_header;          # Not in a course, or no whn priv in course
     $r->print(&display_header());          $env{'user.error.msg'}="/adm/whatsnew::whn:0:0:Cannot display what's new page";
     if (! (($env{'request.course.fn'}) && (&Apache::lonnet::allowed('vsa',$env{'request.course.id'})))) {  
         # Not in a course, or not allowed to modify parms  
         $env{'user.error.msg'}="/adm/whatsnew:vsa:0:0:Cannot display student activity";  
         return HTTP_NOT_ACCEPTABLE;          return HTTP_NOT_ACCEPTABLE;
     }      }
   
       &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;
   
       $r->print(&display_header($command,\%checkallowed));
   
     &Apache::lonhtmlcommon::clear_breadcrumbs();      &Apache::lonhtmlcommon::clear_breadcrumbs();
     if ($command eq 'chgthreshold') {      &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>'/adm/whatsnew',
                 text=>"What's New?"});
       if (($command eq 'chgthreshold') && $checkallowed{'abovethreshold'}) {
         &Apache::lonhtmlcommon::add_breadcrumb          &Apache::lonhtmlcommon::add_breadcrumb
             ({href=>'/adm/whatsnew?command=threshold',              ({href=>'/adm/whatsnew?command=chgthreshold&refpage='.$refpage,
               text=>"Change thresholds"});                text=>"Change thresholds"});
         $r->print(&Apache::lonhtmlcommon::breadcrumbs          $r->print(&Apache::lonhtmlcommon::breadcrumbs
             (undef,'Course Action Items','Course_Action_Items_Thresholds'));              ("What's New?",#'Course_Action_Items_Thresholds'
     } else {       ));
       } elsif (($command eq 'chginterval') && $checkallowed{'versionchanges'} ) {
         &Apache::lonhtmlcommon::add_breadcrumb          &Apache::lonhtmlcommon::add_breadcrumb
             ({href=>'/adm/whatsnew',              ({href=>'/adm/whatsnew?command=chginterval&refpage='.$refpage,
               text=>"Display Action Items"});                text=>"Change interval"});
           $r->print(&Apache::lonhtmlcommon::breadcrumbs
               ("What's New?",#'Course_Action_Items_Intervals'
        ));
       } elsif (($command eq 'chgdisc') && $checkallowed{'coursediscussion'}) {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>'/adm/whatsnew?command=chgdisc&refpage='.$refpage,
                 text=>"Change discussion display"});
         $r->print(&Apache::lonhtmlcommon::breadcrumbs          $r->print(&Apache::lonhtmlcommon::breadcrumbs
             (undef,'Course Action Items','Course_Action_Items_Display'));              ("What's New?",#'Course_Action_Items_Intervals'
        ));
       } elsif ($command eq 'courseinit') {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>'/adm/whatsnew?command=courseinit&refpage='.$refpage,
                 text=>"Course initialization preference"});
           $r->print(&Apache::lonhtmlcommon::breadcrumbs
               ("What's New?",#'Course_Action_Items_Initialization'
        ));
       } elsif ($command eq 'chgoldroleinterval' && $checkallowed{'oldroles'}) {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>'/adm/whatsnew?command=chgoldroleinterval&refpage='.$refpage,
                 text=>"Change interval"});
           $r->print(&Apache::lonhtmlcommon::breadcrumbs
               ("What's New?",#'Course_Action_Items_Intervals'
                ));
       } elsif ($command eq 'chgnewroleinterval' && $checkallowed{'newroles'}) {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>'/adm/whatsnew?command=chgnewroleinterval&refpage='.$refpage,
                 text=>"Change interval"});
           $r->print(&Apache::lonhtmlcommon::breadcrumbs
               ("What's New?",#'Course_Action_Items_Intervals'
                ));
       } else {
           $r->print(&Apache::lonhtmlcommon::breadcrumbs
               ("What's New?",#'Course_Action_Items_Display'
        ));
     }      }
     &display_main_box($r,$command);      &display_main_box($r,$command,$refpage,\%checkallowed);
     return OK;      return OK;
 }  }
   
Line 96  sub handler { Line 158  sub handler {
 #------------------------------  #------------------------------
                                                                                                                                                                   
 sub display_main_box {  sub display_main_box {
     my ($r,$command) = @_;      my ($r,$command,$refpage,$checkallowed) = @_;
     my $domain=&Apache::loncommon::determinedomain();      my $domain=&Apache::loncommon::determinedomain();
     my $tabbg=&Apache::loncommon::designparm('coordinator.tabbg',$domain);      my $function = &Apache::loncommon::get_users_function();
       my $lctype = lc(&Apache::loncommon::course_type());
     $r->print('<table width="100%" border="0" cellpadding="5" cellspacing="0"><tr><td width="100%">');      $r->print('<table width="100%" border="0" cellpadding="5" cellspacing="0"><tr><td width="100%">');
   
     my %threshold_titles = (      my %threshold_titles = &Apache::lonlocal::texthash (
                          av_attempts => 'Average number of attempts',                           av_attempts => 'Average number of attempts',
                          degdiff => 'Degree of difficulty',                           degdiff => 'Degree of difficulty',
                          numstudents => 'Total number of students with submissions',                           numstudents => 'Total number of students with submissions',
     );      );
       my %versions = (
                          -1 => "version changes since start of $lctype",
                     2592000 => 'version changes since last month',
                      604800 => 'version changes since last week',
                       86400 => 'version changes since yesterday',
                      );
       my %newroles = (
                          -1 => "roles which have become active since start of $lctype",
                     2592000 => 'roles which have become active since last month',
                      604800 => 'roles which have become active since last week',
                       86400 => 'roles which have become active since yesterday',
                      );
       my %oldroles = (
                          -1 => "roles which expired since start of $lctype",
                     2592000 => 'roles which expired since last month',
                      604800 => 'roles which expired since last week',
                       86400 => 'roles which expired since yesterday',
                      );
       my %interval_titles = (
           versions => \%versions,
           newroles => \%newroles,
           oldroles => \%oldroles,
       );
       my %initpage = &Apache::lonlocal::texthash (
                        firstres => "first resource in the $lctype",
                        whatsnew => "What's New Page",
                        userpref => 'your general user preferences',
                        coursespecific => "specific setting for this $lctype",
                      );
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};      my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};      my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
   
     if ($command eq 'chgthreshold') {      if (($command eq 'chgthreshold') 
         &display_config_box($r,$command,$tabbg,\%threshold_titles,$cdom,$crs);   && $checkallowed->{'abovethreshold'}) {
           &display_threshold_config($r,$refpage,\%threshold_titles,
                                                                      $cdom,$crs);
       } elsif (($command eq 'chginterval') 
        && $checkallowed->{'versionchanges'}) {
           &display_interval_config($r,$refpage,\%interval_titles,'versions');
       } elsif (($command eq 'chgdisc') 
        && $checkallowed->{'coursediscussion'}) {
           &display_discussion_config($r,$refpage);
       } elsif ($command eq 'courseinit') {
           &courseinit_config($r,$refpage,\%initpage);
       } elsif (($command eq 'chgnewroleinterval')
                && $checkallowed->{'newroles'}) {
           &display_interval_config($r,$refpage,\%interval_titles,'newroles');
       } elsif (($command eq 'chgoldroleinterval')
                && $checkallowed->{'oldroles'}) {
           &display_interval_config($r,$refpage,\%interval_titles,'oldroles');
     } else {      } else {
         &display_actions_box($r,$command,\%threshold_titles,$cdom,$crs);          &display_actions_box($r,$command,$refpage,\%threshold_titles,
                           \%interval_titles,\%initpage,$cdom,$crs,$checkallowed);
     }      }
       my $end_page = &Apache::loncommon::end_page();
     $r->print(<<END_OF_BLOCK);      $r->print(<<END_OF_BLOCK);
   </td>    </td>
  </tr>   </tr>
 </table><br />  </table><br />
 </body>  $end_page
 </html>  
 END_OF_BLOCK  END_OF_BLOCK
 }  }
   
Line 130  END_OF_BLOCK Line 239  END_OF_BLOCK
 # up the HTML  # up the HTML
 #-------------------------------  #-------------------------------
   
 sub display_header{  sub display_header {
     my $html=&Apache::lonxml::xmlbegin();      my ($command,$checkallowed) = @_;
     my $bodytag=&Apache::loncommon::bodytag('Course Action Items');      
     return(<<ENDHEAD);      my $scripttag;
 $html      unless ($command eq 'chgthreshold' || $command eq 'chginterval' || 
 <head>              $command eq 'chgoldroleinterval' || $command eq 'chgnewroleinterval') {
 <title>Course Action Items</title>         $scripttag = <<"END";
 </head>  <script type="text/javascript">
 $bodytag  function change_display(caller,change) {
 ENDHEAD      caller.value = change;
       document.visible.submit();
   }
   
   function changeAll(change) {
   END
           foreach my $item (keys(%{$checkallowed})) {
       if ($item =~ /_section$/) { next; }
               if ($$checkallowed{$item}) {
                   $scripttag.='document.visible.display_'.$item.'.value=change'.
                               "\n";
               }
           }
           $scripttag.='document.visible.submit();
   }
   </script>
   ';
       }
       my $course_type=&Apache::loncommon::course_type();
       return &Apache::loncommon::start_page("What's New?",
     $scripttag);
 }  }
   
 #-------------------------------  #-------------------------------
Line 149  ENDHEAD Line 278  ENDHEAD
 #  #
 #-------------------------------  #-------------------------------
                                                                                                                                                                   
 sub display_actions_box() {  sub display_actions_box {
     my ($r,$command,$threshold_titles,$cdom,$crs) = @_;      my ($r,$command,$refpage,$threshold_titles,$interval_titles,$initpage,
           $cdom,$crs,$checkallowed) = @_;
     my $rowColor1 = "#ffffff";      my $udom = $env{'user.domain'};
     my $rowColor2 = "#eeeeee";      my $uname = $env{'user.name'};
     my $rowColor;      my $cid = $env{'request.course.id'};
       my $crstype = &Apache::loncommon::course_type();
       my $lctype = lc($crstype);
       my %stulabel = (
                       'Course' => 'students',
                       'Community' => 'members',
                      );
       my %lt = &Apache::lonlocal::texthash(
                    'yacc' => 'You are accessing an invalid course',
                    'gtfr' => 'Go to first resource',
                    'hial' => 'Hide all',
                    'shal' => 'Show all',
       );
   
     my %unread = ();      my %unread = ();
     my %ungraded = ();      my %ungraded = ();
     my %bombed = ();      my %bombed = ();
     my %triggered = ();      my %triggered = ();
       my %changed = ();
     my @newmsgs = ();      my @newmsgs = ();
     my @critmsgs = ();      my @critmsgs = ();
     my @newdiscussions = ();      my @newdiscussions = ();
     my @tograde = ();      my @tograde = ();
     my @bombs = ();      my @bombs = ();
     my @warnings = ();      my @warnings = ();
       my $msgcount = 0;
       my $critmsgcount = 0;
       my $expirecount;
       my %expired;
       my $activecount;
       my %activated;
     my %res_title = ();      my %res_title = ();
       my %show = ();
       my $needitems = 0;
       my $boxcount = 0;
   
     my $domain=&Apache::loncommon::determinedomain();      my $result;
     my $function;      if ($command eq 'newcourseinit') {
     if ($env{'request.role'}=~/^(cc|in|ta|ep)/) {          $result = &store_courseinit_setting($uname,$udom,$cid,$initpage);
         $function='coordinator';  
     }  
     if ($env{'request.role'}=~/^(su|dc|ad|li)/) {  
         $function='admin';  
     }      }
   
     my %threshold = (      my %threshold = ();
                       av_attempts => 0,      my %pagedesc = &Apache::lonlocal::texthash (
                       degdiff => 0.01,                       firstres => 'First resource',
                       numstudents => 0,                       whatsnew => "What's New Page",
                      );                       userpref => 'user preference',
                        coursespecific => $lctype.' only',
                        default => 'default',
                      );
   
     my $pgbg=&Apache::loncommon::designparm($function.'.pgbg',$domain);      my ($initcontrol,$initdisp) = &curr_courseinit();
     my $tabbg=&Apache::loncommon::designparm($function.'.tabbg',$domain);      my $currinit = $pagedesc{$initdisp}.' ('.$pagedesc{$initcontrol}.')';
   
     unless ($env{'request.course.id'}) {      unless ($cid) {
         $r->print('<br /><b><center>You are accessing an invalid course.</center></b><br /><br />');          $r->print('<p><span style="text-align: center; font-weight: bold;">'.$lt{'yacc'}.'</span></p>');
         return;          return;
     }      }
   
     my ($furl,$ferr)=      if ($refpage eq 'start') {
            &Apache::lonuserstate::readmap($cdom.'/'.$crs);          if (tie(my %bighash,'GDBM_File',$env{'request.course.fn'}.'.db',
     $r->print('<font size="+1"><a href="'.$furl.'">Go to first resource</a></font><a href="/adm/preferences?action=changecourseinit"></font><br />Change your preferences</a> to suppress display of this screen when accessing courses as Course Coordinator in the future.<br /><hr />');              &GDBM_READER(),0640)) {
               my $furl=$bighash{'first_url'};
     my $result;              untie(%bighash);
               $r->print('<span style="font-size: larger;"><a href="'.$furl.'">'.$lt{'gtfr'}.
                     '</a></span><br />');
           }
       }
       $r->print(&mt('Page set to be displayed after you have selected a role in this '.$lctype).'.'
                 .' <span class="LC_nobreak">'
                 .&mt('Currently: [_1].','<i>'.$currinit.'</i>')
                 .'&nbsp;&nbsp;'
                 .&mt('[_1]Change[_2] for just [_3]this [_4] or for all [_5]your courses/communities[_6].'
                     ,'<b>'
                     ,'</b>'
                     ,'<a href="/adm/whatsnew?command=courseinit&amp;refpage='.$refpage.'">'
                     ,$lctype.'</a>'
                     ,'<a href="/adm/preferences?action=changecourseinit&amp;refpage='.$refpage.'">'
                     ,'</a>')
                 .' </span><br /><hr />');
   
     if ($command eq 'reset') {      if ($command eq 'reset') {
         $result = &process_reset($cdom,$crs);          $result = &process_reset($cdom,$crs);
     } elsif ($command eq 'update') {      } elsif ($command eq 'update') {
         $result = &process_update($cdom,$crs,$threshold_titles);          $result = &process_update($uname,$udom,$threshold_titles);
       } elsif ($command eq 'newinterval') {
           $result = &store_interval_setting($uname,$udom,$cid,$interval_titles);
       } elsif ($command eq 'newdiscconf') {
           $result = &store_discussion_setting($uname,$udom,$cid);
       }
   
       my $store_result=&store_display_settings($uname,$udom,$cid,$checkallowed);
   
       unless ($store_result eq 'ok') { 
           &Apache::lonnet::logthis('Error saving whatsnew settings: '.
               $store_result.' for '.'user '.$uname.':'.$udom.' in '.$lctype.' '.$cid);
           $result .= &mt('Unable to save visibility settings due to [_1]',
                          $store_result); 
     }      }
   
     if ($result) {      if ($result) {
         $r->print($result.'<hr width="100%" />');          $r->print($result.'<hr />');
     }      }
       $r->rflush();
   
     &get_curr_thresholds(\%threshold,$cdom,$crs);      my (%timediff,%interval);
     &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\@newdiscussions,\@tograde,\@bombs,\@warnings,$rowColor1,$rowColor2,\%threshold,$cdom,$crs,%res_title);      my %display_settings = &get_display_settings($uname,$udom,$cid);
     my ($msgcount,$critmsgcount) = &getmail(\@newmsgs,\@critmsgs);      $timediff{'versions'} = $display_settings{$cid.':interval'};
       unless (defined($timediff{'versions'})) { $timediff{'versions'} = 604800; } 
       $interval{'versions'} = $interval_titles->{'versions'}->{$timediff{'versions'}};
   
       my %headings = &Apache::lonlocal::texthash(
                   coursediscussion => 'Unread '.$lctype.' discussion posts',
                   handgrading      => 'Problems requiring handgrading',
                   haserrors        => 'Problems with errors',
                   coursenormalmail => 'New '.$lctype.' messages',
                   coursecritmail   => 'New critical messages in '.$lctype,
       );
   
     $r->print('<br /><table border="0" width="100%" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%">');      if ($timediff{'versions'} == -1) {
           $headings{'versionchanges'} = &mt('Resources in '.$lctype.' with version changes since start of '.$lctype);
       } elsif ($timediff{'versions'} == 2592000) {
           $headings{'versionchanges'} = &mt('Resources in '.$lctype.' with version changes since last month');
       } elsif ($timediff{'versions'} == 604800) {
           $headings{'versionchanges'} = &mt('Resources in '.$lctype.' with version changes since last week');
       } elsif ($timediff{'versions'} == 86400) {
           $headings{'versionchanges'} = &mt('Resources in '.$lctype.' with version changes since yesterday');
       }
   
 ## UNGRADED ITEMS ##      $timediff{'oldroles'} = $display_settings{$cid.':oldroleinterval'};
     $r->print(<<END);      unless (defined($timediff{'oldroles'})) { $timediff{'oldroles'} = 604800; }
            <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000" width="100%">      $interval{'oldroles'} = $interval_titles->{'oldroles'}->{$timediff{'oldroles'}};
             <tr><td>  
              <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000" width="100%">  
               <tr>  
                <td bgcolor="$tabbg"><b>Problems requiring handgrading</b></td></tr>  
                   <tr>  
                    <td bgcolor="#ffffff">  
                      <table cellpadding="2" cellspacing="0" border="0" width="100%">  
 END  
   
     if (@tograde > 0) {      if ($timediff{'oldroles'} == -1) {
         $r->print('<tr bgcolor="#cccccc"><td><b><small>Problem Name</small></b></td><td align="right"><b><small>Number ungraded</small></b></td></tr>');          $headings{'oldroles'} = &mt('Roles for which access to '.$lctype.' has expired since start of '.$lctype);
         my $rowNum = 0;      } elsif ($timediff{'oldroles'} == 2592000) {
         foreach my $res (@tograde) {          $headings{'oldroles'} = &mt('Roles for which access to '.$lctype.' has expired since last month');
             if ($rowNum %2 == 1) {      } elsif ($timediff{'oldroles'} == 604800) {
                 $rowColor = $rowColor1;          $headings{'oldroles'} = &mt('Roles for which access to '.$lctype.' has expired since last week');
             } else {      } elsif ($timediff{'oldroles'} == 86400) {
                 $rowColor = $rowColor2;          $headings{'oldroles'} = &mt('Roles for which access to '.$lctype.' has expired since yesterday');
             }      }
             my ($map,$id,$url)=&Apache::lonnet::decode_symb($res);  
             my $linkurl=&Apache::lonnet::clutter($url);  
             $linkurl .= '?symb='.&Apache::lonnet::escape($res);  
   
             $r->print('<tr bgcolor="'.$rowColor.'"><td><a href="'.$linkurl.'"><small>'.$ungraded{$res}{title}.'</small></a></td><td align="right"><small>'.$ungraded{$res}{count}.'</small></td></tr>');      $timediff{'newroles'} = $display_settings{$cid.':newroleinterval'};
             $rowNum ++;      unless (defined($timediff{'newroles'})) { $timediff{'newroles'} = 604800; }
         }      $interval{'newroles'} = $interval_titles->{'newroles'}->{$timediff{'newroles'}};
     } else {  
         $r->print('<tr><td bgcolor="#ffffff"><br><center><i><b><small>&nbsp;&nbsp;No problems require handgrading&nbsp;&nbsp;</small><br><br></b></i></td></tr>');      if ($timediff{'newroles'} == -1) {
           $headings{'newroles'} = &mt('Roles for which access to '.$lctype.' has become available since start of '.$lctype);
       } elsif ($timediff{'newroles'} == 2592000) {
           $headings{'newroles'} = &mt('Roles for which access to '.$lctype.' has become available since last month');
       } elsif ($timediff{'newroles'} == 604800) {
           $headings{'newroles'} = &mt('Roles for which access to '.$lctype.' has become available since last week');
       } elsif ($timediff{'newroles'} == 86400) {
           $headings{'newroles'} = &mt('Roles for which access to '.$lctype.' has become available since yesterday');
     }      }
     $r->print('</table></td></tr></table></td></tr></table><br />');  
   
 ## BOMBS ##      my $now = time;
      $r->print(<<"END");      if ($timediff{'versions'} == -1) {
            <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000" width="100%">          $timediff{'versions'} = time;
             <tr>  
              <td>  
                <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000" width="100%">  
                <tr>  
                 <td bgcolor="$tabbg"><b>Problems with errors</b></td>  
                </tr>  
                 <tr>  
                 <td bgcolor="#ffffff">  
                  <table width="100%" cellspacing="0" cellpadding="0" border="0">  
 END  
      my $bombnum = 0;  
      if (@bombs > 0) {  
         $r->print('<tr bgcolor="#cccccc"><td><b><small>Resource</small></b></td><td align="right"><b><small>Number of errors</small></b></td></tr>');  
         @bombs = sort { &cmp_title($a,$b,\%res_title) } @bombs;  
         foreach my $bomb (@bombs) {  
             if ($bombnum %2 == 1) {  
                  $rowColor = $rowColor1;  
             } else {  
                 $rowColor = $rowColor2;  
             }  
             $r->print('<tr bgcolor="'.$rowColor.'"><td><small>'.$bombed{$bomb}{errorlink}.'</small></td><td align="right"><small>'.$bombed{$bomb}{errorcount}.'</small></td></tr>');  
             $bombnum ++;  
         }  
     } else {  
         $r->print('<tr><td bgcolor="#ffffff"><br /><center><b><i><small>No problems with errors</small></i></b></center><br /></td></tr>');  
     }      }
     $r->print('</table></td></tr></table></td></tr></table><br />');      my $starttime = $now - $timediff{'versions'};
   
 # DEGDIFF AND AV. TRIES TRIGGERS      if ($timediff{'newroles'} == -1) {
     $r->print(<<"END");          $timediff{'newroles'} = time;
            <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000" width="100%">      }
             <tr>      my $activatedstart = $now - $timediff{'newroles'};
              <td>  
                <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000" width="100%">      if ($timediff{'oldroles'} == -1) {
                <tr>          $timediff{'oldroles'} = time;
                 <td bgcolor="$tabbg"><b>Problems with av. attempts &ge; $threshold{'av_attempts'} or deg. difficulty &ge; $threshold{'degdiff'}<br /> and total number of students with submissions &ge; $threshold{'numstudents'}</b></td>      }
                </tr>      my $expiredstart = $now - $timediff{'oldroles'};
                <tr>  
                 <td bgcolor="$tabbg" align="right"><a href="/adm/whatsnew?command=chgthreshold"><b><small>Change thresholds?</small></b></a></td>      my $countunread = $display_settings{$cid.':countunread'};
                </tr>      unless (defined($countunread)) {
                 <tr>          $countunread = 'on';
                 <td bgcolor="#ffffff">      }
                  <table width="100%" cellspacing="2" cellpadding="2" border="0">      if ($$checkallowed{'abovethreshold'}) {
 END          &get_curr_thresholds(\%threshold,$uname,$udom,$cid,$cdom,$crs);
     my $warningnum = 0;      }
     if (@warnings > 0) {  
         @warnings = sort { &cmp_title($a,$b,\%res_title) } @warnings;      $headings{'abovethreshold'} = 
         $r->print('<form name="reset_tracking" method="post">'.   &mt('(Problems with av. attempts &ge; [_1] or deg. difficulty &ge; [_2]) [_3] and total number of '.$stulabel{$crstype}.' with submissions &ge; [_4]',
                  '  <input type="hidden" name="action" value="reset" />'."\n");      $threshold{'av_attempts'},$threshold{'degdiff'},
         $r->print('<tr bgcolor="#cccccc"><td><b><small>Resource</small></b></td><td align="right"><b><small>Part</small></b></td><td align="right"><b><small>Num. students</small></b></td><td align="right"><b><small>Av. Attempts</small></b></td><td align="right"><b><small>Deg. Diff</small></b></td><td align="right"><b><small>Last Reset</small></b></td><td align="right"><b><small>Reset Count?</small></b></td></tr>');      '<br />',$threshold{'numstudents'});
         foreach my $res (@warnings) {  
             if ($warningnum %2 == 1) {      my @actionorder = ('handgrading','haserrors','abovethreshold','versionchanges','coursediscussion','coursenormalmail','coursecritmail','newroles','oldroles');
                 $rowColor = $rowColor1;  
             } else {      foreach my $key (keys(%{$checkallowed})) {
                 $rowColor = $rowColor2;   if ($key =~ /_section$/) { next; }
             }          $show{$key} = 0;
             my ($map,$id,$url)=&Apache::lonnet::decode_symb($res);          if ($$checkallowed{$key}) {
             my $linkurl=&Apache::lonnet::clutter($url);              unless ($display_settings{$cid.':'.$key} eq 'hide') {
             my $rowspan;                  $show{$key} = 1;
             if ($triggered{$res}{numparts} > 1) {  
                 $rowspan = 'rowspan="'.$triggered{$res}{numparts}.'"';  
             }  
             $linkurl .= '?symb='.&Apache::lonnet::escape($res);  
             $r->print('<tr bgcolor="'.$rowColor.'"><td '.$rowspan.'><a href="'.$linkurl.'"><small>'.$triggered{$res}{title}.'</small></a></td>'.$triggered{$res}{text});  
             $warningnum ++;  
         }  
         $r->print('<tr bgcolor="#cccccc"><td colspan="7" align="right"><br /><b><small><input type="submit" name="counters" value="Reset counters to 0" /></form>');   
     } else {  
         $r->print('<tr><td bgcolor="#ffffff"><br /><center><b><i><small>No problems satisfy threshold criteria.</small></i></b></center><br /></td></tr>');  
     }  
     $r->print('</table></td></tr></table></td></tr></table><br />');  
   
     $r->print('</td><td width="5%">&nbsp;</td><td align="left" valign="top" width-"50%">');  
   
 ## UNREAD COURSE DISCUSSION POSTS ##  
     $r->print(<<"END");  
               <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000" width="100%">  
                <tr><td>  
                 <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000" width="100%">  
                  <tr>  
                   <td bgcolor="$tabbg"><b>Unread course discussion posts</b></td>  
                  </tr>  
                  <tr>  
                    <td bgcolor="#ffffff">  
                    <table cellpadding="2" cellspacing="0" border="0" width="100%">  
 END  
                                                                                     
     if (@newdiscussions > 0) {  
         $r->print('<tr bgcolor="#cccccc"><td><b><small>Location</small></b></td><td><b><small>Type</small></b><td align="right"><b><small>Number of new posts</small></b></td></tr>');  
         @newdiscussions = sort { &cmp_title($a,$b,\%res_title) } @newdiscussions;  
         my $rowNum = 0;  
         foreach my $ressymb (@newdiscussions) {  
             my $forum_title = $unread{$ressymb}{'title'};  
             my $type = 'Resource';  
             my $feedurl=&Apache::lonfeedback::get_feedurl($ressymb);  
             if ($feedurl =~ /bulletinboard/) {  
                 $type = 'Bulletin Board';  
             }  
             my $unreadnum = keys(%{$unread{$ressymb}});  
             $unreadnum = $unreadnum - 2;  
             if ($unreadnum > 0) {  
                 if ($rowNum %2 == 1) {  
                     $rowColor = $rowColor1;  
                 } else {  
                     $rowColor = $rowColor2;  
                 }  
                 $r->print('<tr bgcolor="'.$rowColor.'"><td><small><a href="'.$feedurl.'?symb='.$unread{$ressymb}{symb}.'">'.$forum_title.'</a>&nbsp;</td><td><small>'.$type.'</small></td><td align="right">'.$unreadnum.'&nbsp;</td></tr>');  
                 $rowNum ++;  
             }              }
         }          }
     } else {  
         $r->print('<tr><td bgcolor="#ffffff"><br><center>&nbsp;<i><b><small>No unread posts in course discussions</small></b></i><br><br></td></tr>');  
     }      }
     $r->print('</table></td></tr></table></td></tr></table><br />');  
   
 ## MESSAGES ##      foreach my $item (@actionorder) {
     $r->print(<<END);          unless ($item eq 'coursenormalmail' || $item eq 'coursecritmail' ||
            <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000" width="100%">                  $item eq 'newroles' || $item eq 'oldroles') {
             <tr>              if ($show{$item}) {
              <td>                  $needitems = 1;
               <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000" width="100%">                  last;
                <tr>  
                 <td bgcolor="$tabbg"><b>New course messages</b></td>  
                </tr>  
                <tr>  
                 <td bgcolor="#ffffff">  
                  <table width="100%" cellspacing="0" cellpadding="0" border="0">  
 END  
     if ($msgcount > 0) {  
         $r->print('<tr bgcolor="#cccccc"><td><b><small>'.&mt('Number').'</small></b></td><td><b><small>'.&mt('Subject').'</small></b></td><td><b><small>'.&mt('Sender').'</small></b></td><td><b><small>'.&mt('Date/Time').'</small></b></td></tr>');  
         my $rowNum = 0;  
         my $mailcount = 1;   
         foreach my $msg (@newmsgs) {  
             if ($rowNum %2 == 1) {  
                 $rowColor = $rowColor1;  
             } else {  
                 $rowColor = $rowColor2;  
             }              }
             $r->print('<tr bgcolor="'.$rowColor.'"><td valign="top"><small>'.$mailcount.'. &nbsp;<small></td><td valign="top"><small><a href="/adm/mail?">'.$msg->{'shortsub'}.'</a>&nbsp; &nbsp;</small></td><td valign="top"><small>&nbsp;'.$msg->{'from'}.'@'.$msg->{'fromdom'}.'&nbsp;</small></td><td valign="top"><small>'.$msg->{'sendtime'}.'</small></td></tr>');  
             $rowNum ++;  
             $mailcount ++;  
         }          }
     } else {  
         $r->print('<tr><td bgcolor="#ffffff" width="100%"><center><br /><b><i><small>No new course messages</small></i></b><br /><br /></center></td></tr>');  
     }      }
   
     $r->print('</table></td></tr></table></td></tr></table><br />');      my $itemserror;
       if ($needitems) {
           $itemserror = &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\%changed,\@newdiscussions,\@tograde,\@bombs,\@warnings,\%threshold,$cdom,$crs,\%res_title,\%show,$starttime,$countunread);
       }
       if ($show{'coursenormalmail'}) {
           $msgcount = &getnormalmail(\@newmsgs);
       }
       if ($show{'coursecritmail'}) {
           $critmsgcount = &getcritmail(\@critmsgs);
       }
       if ($show{'oldroles'}) {
           $expirecount = &getexpired(\%expired,$expiredstart,'previous');
       }
       if ($show{'newroles'}) {
           $activecount = &getactivated(\%activated,$activatedstart,'active');
       }
       $r->print(qq|<a href="javascript:changeAll('hide');">$lt{'hial'}</a>
        &nbsp;&nbsp;<a href="javascript:changeAll('show');">$lt{'shal'}</a>
        <form method="post" name="visible" action="/adm/whatsnew">\n|);
       foreach my $item (keys(%{$checkallowed})) {
    if ($item =~ /_section$/) { next; }
           if ($$checkallowed{$item}) {
               $r->print('<input type="hidden" name="display_'.$item.'" />'."\n");
           }
       }
   
     $r->print(<<END);      $r->print('<input type="hidden" name="refpage" value="'.$refpage.'" /></form><table class="LC_double_column"><tr><td class="LC_left_col">');
            <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000" width="100%">  
             <tr>  
              <td>  
               <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000" width="100%">  
                <tr>  
                 <td bgcolor="$tabbg"><b>New critical messages in course</b></td>  
                </tr>  
                <tr>                 <td bgcolor="#ffffff">  
                  <table width="100%" cellspacing="0" cellpadding="0" border="0">  
 END  
   
     if ($critmsgcount > 0) {      my $displayed = 0;
         $r->print('<tr bgcolor="#cccccc"><td><b><small>Number</small></b></td><td><b><small>Subject</small></b></td><td><b><small>Sender</small></b></td><td><b><small>Date/Time</small></b></td></tr>');      my $totalboxes = 0;
         my $rowNum = 0;      foreach my $key (keys(%{$checkallowed})) {
         my $mailcount = 1;   if ($key =~ /_section$/) { next; }
         foreach my $msg (@critmsgs) {   if ($key eq 'whatsnew' ) { next; } # whatsnew check creates no box
             if ($rowNum %2 == 1) {          if ($$checkallowed{$key}) {
                 $rowColor = $rowColor1;              $totalboxes ++;
             } else {          }
                 $rowColor = $rowColor2;      }
       my $halfway = 4;
   #    my $halfway = int($totalboxes/2) + $totalboxes%2;
       foreach my $actionitem (@actionorder) {
           if ($$checkallowed{$actionitem}) {
               if ($displayed == $halfway) {
                   $r->print('</td><td>&nbsp;</td><td class="LC_right_col" >');
             }              }
             $r->print('<tr bgcolor="'.$rowColor.'"><td valign="top"><small>'.$mailcount.'. &nbsp;<small></td><td valign="top"><small><a href="/adm/mail?">'.$msg->{'shortsub'}.'</a>&nbsp; &nbsp;</small></td><td valign="top"><small>&nbsp;'.$msg->{'from'}.'@'.$msg->{'fromdom'}.'&nbsp;</small></td><td valign="top"><small>'.$msg->{'sendtime'}.'</small></td></tr>');              &display_launcher($r,$actionitem,$refpage,$checkallowed,\%show,\%headings,\%res_title,\@tograde,\%ungraded,\@bombs,\%bombed,\%changed,\@warnings,\%triggered,\@newdiscussions,\%unread,$msgcount,\@newmsgs,$critmsgcount,\@critmsgs,\%interval,$countunread,\%expired,$expirecount,\%activated,$activecount,$crstype,$itemserror);
             $rowNum ++;              $displayed ++; 
             $mailcount ++;  
         }          }
     } else {  
         $r->print('<tr><td bgcolor="#ffffff" width="100%"><center><br /><b><i><small>No unread critical messages in course</small></i></b><br /><br /></center></td></tr>');  
     }      }
                                                                                  
     $r->print('</table></td></tr></table></td></tr></table><br />');  
   
     $r->print('      $r->print('
            </table>        </td>
           </td>      </tr>
          </tr>     </table>
         </table>');  ');
     $r->print('</td></tr></table>');  
 }  }
   
 #-------------------------------  #-------------------------------
 # display_config_box  # display_threshold_config
 #  #
 # Display the threshold setting screen   # Display the threshold setting screen 
 #  #
 #-------------------------------  #-------------------------------
                                                                                                                                                                   
 sub display_config_box() {  sub display_threshold_config {
     my ($r,$command,$tabbg,$threshold_titles,$cdom,$crs) = @_;      my ($r,$refpage,$threshold_titles,$cdom,$crs) = @_;
       my $uname = $env{'user.name'};
       my $udom = $env{'user.dom'};
       my $cid = $env{'request.course.id'};
     my %threshold = ();      my %threshold = ();
     my $rowColor1 = "#ffffff";      my $rowColor1 = "#ffffff";
     my $rowColor2 = "#eeeeee";      my $rowColor2 = "#eeeeee";
     my $rowColor;      my $rowColor;
   
     my @thresholditems = ("av_attempts","degdiff","numstudents");      my @thresholditems = ("av_attempts","degdiff","numstudents");
     my %threshold_titles = (      my %threshold_titles = &Apache::lonlocal::texthash(
                          av_attempts => 'Average number of attempts',                           av_attempts => 'Average number of attempts',
                          degdiff => 'Degree of difficulty',                           degdiff => 'Degree of difficulty',
                          numstudents => 'Total number of students with submissions',                           numstudents => 'Total number of students with submissions',
                          );                           );
     &get_curr_thresholds(\%threshold,$cdom,$crs);      &get_curr_thresholds(\%threshold,$uname,$udom,$cid,$cdom,$crs);
   
     $r->print('<br /><form name="thresholdform" method="post"><table border="0" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%">      $r->print('<br /><form name="thresholdform" method="post" action="/adm/whatsnew">'.
            <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000">                &Apache::loncommon::start_data_table().
             <tr>                &Apache::loncommon::start_data_table_header_row().
              <td>               '<th>'.&mt('Threshold Name').'</th>'."\n".
                <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000">               '<th>'.&mt('Current value').'</th>'."\n".
                 <tr>               '<th>'.&mt('Change?').'</th>'."\n".
                 <td bgcolor="#ffffff">                &Apache::loncommon::end_data_table_header_row());
                  <table cellspacing="0" cellpadding="4" border="0">  
      <tr bgcolor="'.$tabbg.'">  
       <th>Threshold Name</th>  
       <th>Current value</th>  
       <th>Change?</th>  
      </tr>');  
     my $rowNum =0;  
     foreach my $type (@thresholditems) {      foreach my $type (@thresholditems) {
         my $parameter = 'internal.threshold_'.$type;          my $parameter = $env{'request.course.id'}.':threshold_'.$type;
 # onchange is javascript to automatically check the 'Set' button.  # onchange is javascript to automatically check the 'Set' button.
         my $onchange = 'onFocus="javascript:window.document.forms'.          my $onchange = 'onFocus="javascript:window.document.forms'.
               "['thresholdform'].elements['".$parameter."_setparmval']".                "['thresholdform'].elements['".$parameter."_setparmval']".
               '.checked=true;"';                '.checked=true;"';
         if ($rowNum %2 == 1) {          $r->print(&Apache::loncommon::start_data_table_row()."\n".
             $rowColor = $rowColor1;                   '<td>'.$threshold_titles{$type}.'</td>'."\n".
         } else {                   '<td>'.&Apache::lonhtmlcommon::textbox($parameter.'_value',
             $rowColor = $rowColor2;  
         }  
         $r->print('  
      <tr bgcolor="'.$rowColor.'">  
       <td>'.$threshold_titles{$type}.'</td>  
       <td>'.&Apache::lonhtmlcommon::textbox($parameter.'_value',  
                                             $threshold{$type},                                              $threshold{$type},
                                             10,$onchange).'</td>                                              10,$onchange).'</td>'."\n".
       <td>'                   '<td>'.
            .&Apache::lonhtmlcommon::checkbox($parameter.'_setparmval').                   &Apache::lonhtmlcommon::checkbox($parameter.'_setparmval').
       '</td>                   '</td>'."\n".
      </tr>');                   &Apache::loncommon::end_data_table_row());
         $rowNum ++;      }
     }      $r->print(&Apache::loncommon::end_data_table()."\n".
     $r->print('</table></td></tr></table></td></tr></table>            '<br /><input type="submit" name="threshold" value="'.&mt('Save').'" />
            <br /><input type="submit" name="threshold" value="Make changes" />                   <input type="hidden" name="command" value="update" />
                  <input type="hidden" name="action" value="update" />                   <input type="hidden" name="refpage" value="'.$refpage.'" />
                  </form>');
   }
   
   #-------------------------------
   # display_interval_config
   #
   # Display the interval setting screen
   #
   #-------------------------------
                                                                                      
   sub display_interval_config {
       my ($r,$refpage,$interval_titles,$context) = @_;
       my $setting = 'interval';
       if ($context eq 'oldroles') {
           $setting = 'oldroleinterval';
       } elsif ($context eq 'newroles') {
           $setting = 'newroleinterval'; 
       }
       my $lctype = lc(&Apache::loncommon::course_type());
       my $current = &get_current($env{'user.name'},$env{'user.domain'},
                                   $env{'request.course.id'},$setting);
       if ($context eq 'oldroles') {
           $r->print('<br />'.&mt('Choose the time window to use to display roles for which access to the '.$lctype.' expired.').'<br />');
       } elsif ($context eq 'newroles') {
           $r->print('<br />'.&mt('Choose the time window to use to display roles for which access to the '.$lctype.' became available.').'<br />');
       } else {
           $r->print('<br />'.&mt('Choose the time window to use to display resources in the '.$lctype.' with version changes.').'<br />');
       }
       unless ($current eq '') {
           if (ref($interval_titles->{$context}) eq 'HASH') {
               $r->print(' '.&mt('Current value is "[_1]".','<b>'.
                         $interval_titles->{$context}->{$current}.'</b>').'<br />');
           }
       }
       $r->print('<br />
   <form method="post" name="intervalswitch" action="/adm/whatsnew">
   <input type="hidden" name="command" value="newinterval" />
   <input type="hidden" name="intervaltype" value="'.$context.'" />
   <input type="hidden" name="refpage" value="'.$refpage.'" />'.
   &mt('Display:').' 
   <select name="interval">
   <option value="" selected="selected">'.&mt('Select').'</option>
   ');
       if (ref($interval_titles) eq 'HASH') {
           if (ref($interval_titles->{$context}) eq 'HASH') {
               foreach my $key (reverse sort ({$a cmp $b} (keys(%{$interval_titles->{$context}})))) {
                   $r->print('<option value="'.$key.'">'.&mt($interval_titles->{$context}->{$key}).
                             '</option>'."\n");
               }
           }
       }
       $r->print('</select>&nbsp;&nbsp;
                  <input type="submit" name="display" value="'.
                  &mt('Save').'" /></form>');
       return;
   }
   
   #----------------------------------------------
   # display_discussion_config
   #
   # Display the discussion display setting screen
   #
   #----------------------------------------------
                                                                                     
   sub display_discussion_config {
       my ($r,$refpage) = @_;
       my $current = &get_current($env{'user.name'},$env{'user.domain'},
                                   $env{'request.course.id'},'countunread');
       if ($current eq '') {
           $current = 'on';
       }
       my %opposite = ( 
                         'on' => 'off',
                         'off' => 'on',
                       );
       $r->print('<script type="text/javascript">
   function toggle_countunread(choice) {
       if (choice == "unchanged") {
           document.discussionswitch.command.value = "";
       }
       document.discussionswitch.submit();
   }
   </script>');
       $r->print('<br />'
                .&mt('Choose whether or not to display a count of the number of new posts for each resource or discussion board which has unread posts.')
                .'<br />'
                .&mt("This can increase the time taken to gather data for the [_1]What's New Page[_2] by a few seconds.",'<i>','</i>')
                .'&nbsp;&nbsp;'
                .&mt('Currently set to [_1].','<b>'.$current.'</b>.')
       );
       $r->print('<br /><br />
   <form method="post" name="discussionswitch" action="/adm/whatsnew">
   <input type="hidden" name="command" value="newdiscconf" />
   <input type="hidden" name="refpage" value="'.$refpage.'" />
   <input type="hidden" name="countunread" value="'.$opposite{$current}.'" />
   ');
       $r->print('<br/>
                  <input type="button" name="display" value="'.
                  &mt('Change to [_1]',&mt($opposite{$current})).'" 
                  onclick="javascript:toggle_countunread('."'change'".')" />'.
                  ('&nbsp;' x7).
                  '<input type="button" name="nochange" value="'.
                  &mt("No change").'" 
                  onclick="javascript:toggle_countunread('."'unchanged'".')" />
                </form>');                 </form>');
       return;
   }
   
   #---------------------------------------------------
   # courseinit_config
   #
   # Set page displayed when course loads after 
   # selecting a role in the course from the roles page. 
   #
   #---------------------------------------------------
   
   sub courseinit_config {
       my ($r,$refpage,$initpage) = @_;
       my ($control,$current) = &curr_courseinit();
       my @chgstate = ('userpref','coursespecific');
       my @chgentry = ('firstres','whatsnew');
       my $lctype = lc(&Apache::loncommon::course_type());
       my %lt = &Apache::lonlocal::texthash(
                                'chwp' => "Choose which page will be displayed when you enter this $lctype after selecting a role.",
                                'cuva' => 'Current value is determined by',
                                'anis' => 'and is set to display',
                                'padc' => 'Page display controlled by',
                                'chce' => 'Choose '.$lctype.' entry',
                                'moce' => 'Save',
       );
       $r->print(<<"END"); 
   <br />$lt{'chwp'}
   <br />$lt{'cuva'}: <b>
   $$initpage{$control}</b> $lt{'anis'} <b>
   $$initpage{$current}</b>.<br /><br />
   <form method="post" name="courseinitswitch" action="/adm/whatsnew">
   <input type="hidden" name="command" value="newcourseinit" />
   <input type="hidden" name="refpage" value="$refpage" />
   $lt{'padc'}:&nbsp;&nbsp;
   END
       foreach my $choice (@chgstate) {
           my $chkstring;
           if ($choice eq $control) {
               $chkstring = ' checked="checked" ';
           }  
           $r->print('<span class="LC_nobreak"><label><input type="radio" name="courseinit_control" value="'.
                      $choice.'"'.$chkstring.'/>'.$$initpage{$choice}.
                      '&nbsp;&nbsp;</label></span>');
       }
       $r->print('<br /><br />'.&mt('If').' '.$$initpage{'coursespecific'}.
                 ' - <br />'.$lt{'chce'}.": \n");
       foreach my $choice (@chgentry) {
           my $chkstring;
           if (($choice eq $current) && ($control eq 'coursespecific')) {
               $chkstring = ' checked="checked" ';
           }
           $r->print('<span class="LC_nobreak"><label><input type="radio" name="courseinit_page" value="'.
                     $choice.'"'.$chkstring.'/>'.$$initpage{$choice}.
                     '&nbsp;&nbsp;</label></span>');
       }
       $r->print('<br /><br /><input type="submit" name="display" value="'.
                  $lt{'moce'}.'" /></form>');
       return;
   }
   
   sub curr_courseinit {
       my $current = &get_current($env{'user.name'},$env{'user.domain'},
                                   $env{'request.course.id'},'courseinit');
       my $control;
       if ($current) {
           $control = 'coursespecific';
       } else {
           $control = 'userpref';
           my %userenv = &Apache::lonnet::get('environment',
                                                         ['course_init_display']);
           if (exists($userenv{'course_init_display'})) {
               $current = $userenv{'course_init_display'};
           }
           unless ($current) {
               $current = 'whatsnew';
           }
       }
       return ($control,$current);
   }
   
   sub display_launcher {
       my ($r,$action,$refpage,$checkallowed,$show,$headings,$res_title,
           $tograde,$ungraded,$bombs,$bombed,$changed,$warnings,$triggered,
           $newdiscussions,$unread,$msgcount,$newmsgs,$critmsgcount,$critmsgs,
           $interval,$countunread,$expired,$expirecount,$activated,$activecount,
           $crstype,$itemserror) = @_;
   
       if ($$checkallowed{$action}) {
           &start_box($r,$show,$headings,$action,$refpage,$action);
           if ($$show{$action}) {
               if ($action eq 'handgrading') {    # UNGRADED ITEMS
                   &display_handgrade($r,$tograde,$ungraded,$itemserror);
               } elsif ($action eq 'haserrors') { # BOMBS
                   &display_haserrors($r,$bombs,$bombed,$res_title,$itemserror);
               } elsif ($action eq 'versionchanges') { # VERSION CHANGES
                   &display_versionchanges($r,$changed,$res_title,$interval->{'versions'},$itemserror);
               } elsif ($action eq 'abovethreshold') { # DEGDIFF/AV. TRIES TRIGGERS
                   &display_abovethreshold($r,$refpage,$warnings,$triggered,
    $res_title,$itemserror);
               } elsif ($action eq 'coursediscussion') { # UNREAD COURSE DISCUSSION
                   &display_coursediscussion($r,$newdiscussions,$unread,
                                   $countunread,$res_title,$itemserror);
               } elsif ($action eq 'coursenormalmail') { # NORMAL MESSAGES
                   &display_coursenormalmail($r,$msgcount,$newmsgs);
               } elsif ($action eq 'coursecritmail') { # CRITICAL MESSAGES
                   &display_coursecritmail($r,$critmsgcount,$critmsgs);
               } elsif ($action eq 'newroles') { # ACTIVATED ROLES
                   &display_rolechanges($r,$activecount,$activated,$interval->{'newroles'},
                                        $crstype);
               } elsif ($action eq 'oldroles') { # EXPIRED ROLES
                   &display_rolechanges($r,$expirecount,$expired,$interval->{'oldroles'},
                                        $crstype);
               }
           }
           &end_box($r);
       }
       return;
 }  }
   
 sub getitems {  sub getitems {
     my ($unread,$ungraded,$bombed,$triggered,$newdiscussions,$tograde,$bombs,$warnings,$rowColor1,$rowColor2,$threshold,$cdom,$crs,$res_title) = @_;      my ($unread,$ungraded,$bombed,$triggered,$changed,$newdiscussions,
           $tograde,$bombs,$warnings,$threshold,$cdom,$crs,$res_title,$show,
           $starttime,$countunread) = @_;
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
     my @allres=$navmap->retrieveResources();      if (!defined($navmap)) {
     my %discussiontime = &Apache::lonnet::dump('discussiontimes',$cdom,$crs);          my $itemserror = '<span class="LC_warning">'.&mt('An error occurred retrieving information about the course.').'<br />'.&mt('It is recommended that you [_1]re-select the course[_2].','<a href="/adm/roles">','</a>').'</span>';
     my %lastread = &Apache::lonnet::dump('nohist_'.$env{'request.course.id'}.          return $itemserror;
                 '_discuss',$env{'user.domain'},$env{'user.name'},'lastread');      }
     my %lastreadtime = ();      # force retrieve Resource to seed the part id cache we'll need it later
     my @discussions = ();      my @allres=$navmap->retrieveResources(undef,
     my ($classlist,$keylist) = &Apache::loncoursedata::get_classlist();                       sub {if ($_[0]->is_problem) { $_[0]->parts();} return 1;});
       my %resourcetracker;
     my %resourcetracker =  &Apache::lonnet::dump('nohist_resourcetracker',      my $discussiontime;
                $cdom,$crs);  
     my $warningnum = 0;  # Resource version changes
     foreach my $key (keys(%lastread)) {      if ($$show{'versionchanges'}) {
         my $newkey = $key;          &checkversions($cdom,$crs,$navmap,$changed,$starttime);
         $newkey =~ s/_lastread$//;      }
         $lastreadtime{$newkey} = $lastread{$key};  
       if ($$show{'abovethreshold'}) {
           %resourcetracker =  &Apache::lonnet::dump('nohist_resourcetracker',
                                                                      $cdom,$crs);
     }      }
   
     foreach my $resource (@allres) {      foreach my $resource (@allres) {
         my $result = '';          my $result = '';
         my $applies = 0;          my $applies = 0;
         my $symb = $resource->symb();          my $symb = $resource->symb();
 #        %{$$bombed{$symb}} = ();          %{$$bombed{$symb}} = ();
         %{$$ungraded{$symb}} = ();          %{$$ungraded{$symb}} = ();
         %{$$triggered{$symb}} = ();          %{$$triggered{$symb}} = ();
         $$triggered{$symb}{numparts} = 0;          $$triggered{$symb}{numparts} = 0;
           if ($resource->encrypted()) {
               $$triggered{$symb}{'enclink'} = $resource->link();
               $$triggered{$symb}{'encsymb'} = $resource->shown_symb();
           }
         my $title = $resource->compTitle();          my $title = $resource->compTitle();
         $$res_title{$symb} = $title;          $$res_title{$symb} = $title;
         my $ressymb = $resource->wrap_symb();          my $ressymb = $resource->wrap_symb();
 # Check for unread discussion postings  
         if (defined($discussiontime{$ressymb})) {  # Check if there are unread discussion postings
             push(@discussions,$ressymb);          if ($$show{'coursediscussion'}) {
             my $prevread = 0;              &check_discussions($resource,$symb,$ressymb,$title,
             my $unreadcount = 0;         $newdiscussions,$unread,$countunread);
             %{$$unread{$ressymb}} = ();          }
             $$unread{$ressymb}{'title'} = $title;  
             $$unread{$ressymb}{'symb'} = $symb;  
             if (defined($lastreadtime{$ressymb})) {  
                 $prevread = $lastreadtime{$ressymb};  
             }  
             my %contrib = &Apache::lonnet::restore($ressymb,  
                              $env{'request.course.id'},$cdom,$crs);  
             if ($contrib{'version'}) {  
                 for (my $id=1;$id<=$contrib{'version'};$id++) {  
                     unless (($contrib{'hidden'}=~/\.$id\./) || ($contrib{'deleted'}=~/\.$id\./)) {  
                         if ($prevread <$contrib{$id.':timestamp'}) {  
                             $$unread{$ressymb}{$unreadcount} = $id.': '.$contrib{$id.':subject'};  
                             $unreadcount ++;  
                         }  
                     }  
                 }  
             }  
             if ($unreadcount) { push(@{$newdiscussions}, $ressymb); }  
  }  
   
 # Check for ungraded problems  # Check for ungraded problems
         if ($resource->is_problem()) {          if ($resource->is_problem()) {
             my $ctr = 0;              if ($$show{'handgrading'}) {
             my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);                  &check_handgraded($resource,$symb,$title,$cdom,$crs,$ungraded,
             my ($partlist,$handgrade,$responseType) = &Apache::grades::response_type($url,$symb);                                                                       $tograde);
             foreach my $student (keys(%$classlist)) {              }
                 my ($uname,$udom) = split(/:/,$student);          }
                 my %status=&Apache::grades::student_gradeStatus($url,$symb,$udom,$uname,$partlist);  
                 my $submitted = 0;  # Check for bombs
                 my $ungraded = 0;          if ($$show{'haserrors'}) {
                 foreach (keys(%status)) {              &check_bombed($resource,$symb,$title,$bombs,$bombed);
                     $submitted = 1 if ($status{$_} ne 'nothing');          }
                     $ungraded = 1 if ($status{$_} =~ /^ungraded/);  
                     my ($foo,$partid,$foo1) = split(/\./,$_);  # Maxtries and degree of difficulty for problem parts, unless handgradeable
                     if ($status{'resource.'.$partid.'.submitted_by'} ne '') {          if ($$show{'abovethreshold'}) {  
                         $submitted = 0;              &check_thresholds($resource,$symb,\%resourcetracker,
                     }        $triggered,$threshold,$warnings);
                 }          }
                 next if (!$submitted || !$ungraded);  
                 $ctr ++;      }
       return; 
   }
   
   sub check_discussions {
       my ($resource,$symb,$ressymb,$title,$newdiscussions,$unread,
    $countunread) = @_;
   
       if (!$resource->hasDiscussion()) { return; }
   
       %{$$unread{$ressymb}} = ();
       $$unread{$ressymb}{'title'} = $title;
       $$unread{$ressymb}{'symb'} = $symb;
       if ($resource->encrypted()) {
           $$unread{$ressymb}{'enclink'} = $resource->link();
           $$unread{$ressymb}{'encsymb'} = $resource->shown_symb();
       }
       push(@{$newdiscussions}, $ressymb);
       
       $$unread{$ressymb}{'lastpost'} = $resource->last_post_time();
       
       if ($countunread eq 'on') {
    $$unread{$ressymb}{'unreadcount'} = 
                               $resource->discussion_info('unread');
       }
   }
   
   sub check_handgraded {
       my ($resource,$symb,$title,$cdom,$cnum,$ungraded,$tograde) = @_;
       if ($resource->is_problem()) {
           my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
           my $partlist=$resource->parts();
           my $handgradeable;
           foreach my $part (@$partlist) {
               if ($resource->handgrade($part) eq 'yes') {
                   $handgradeable=1; last;
             }              }
             if ($ctr) {          }
                 $$ungraded{$symb}{count} = $ctr;          if ($handgradeable) {
               my @ungraded = &Apache::bridgetask::get_queue_symb_status(
                                                'gradingqueue',$symb,$cdom,$cnum);
               if (@ungraded > 0) {
                   $$ungraded{$symb}{count} = scalar(@ungraded);
                 $$ungraded{$symb}{title} = $title;                  $$ungraded{$symb}{title} = $title;
                 push(@{$tograde}, $symb);                  if ($resource->encrypted()) {
                       $$ungraded{$symb}{'enclink'} = $resource->link();
                       $$ungraded{$symb}{'encsymb'} = $resource->shown_symb();
                   }
                   push(@{$tograde},$symb);
             }              }
         }          }
       }
   }
   
 # Check for bombs  sub check_bombed {
         if ($resource->getErrors()) {      my ($resource,$symb,$title,$bombs,$bombed) = @_;
             my $errors = $resource->getErrors();      if ($resource->getErrors()) {
             $errors =~ s/^,//;          my $errors = $resource->getErrors();
             my @bombs = split(/,/, $errors);          $errors =~ s/^,//;
             my $errorcount = scalar(@bombs);          my @bombs = split(/,/, $errors);
             my $errorlink = '<a href="/adm/email?display='.          my $errorcount = scalar(@bombs);
                             &Apache::lonnet::escape($bombs[0]).'">'.          my $errorlink = '<a href="/adm/email?display='.
                             $title.'</a>';                          &escape($bombs[0]).'">'.
             $$bombed{$symb}{errorcount} = $errorcount;                          $title.'</a>';
             $$bombed{$symb}{errorlink} = $errorlink;          $$bombed{$symb}{errorcount} = $errorcount;
             push(@{$bombs}, $symb);          $$bombed{$symb}{errorlink} = $errorlink;
         }          push(@{$bombs}, $symb);
 # Compile maxtries and degree of difficulty for problem parts      }
         my @parts = @{$resource->parts()};  }
         my %stats;  
         my %lastreset = ();  sub check_thresholds {
         my $warning = 0;      my ($resource,$symb,$resourcetracker,$triggered,$threshold,$warnings) = @_;
         my $rowColor;  # Compile maxtries and degree of difficulty for problem parts, unless handgradeable
         foreach my $part (@parts) {      my @parts = @{$resource->parts()};
             %{$stats{$part}} = ();      my %stats;
             my ($attempts,$users,$corrects,$degdiff,$av_attempts);      my %lastreset = ();
             if (exists($resourcetracker{$symb."\0".$part."\0attempts"})) {      my $warning = 0;
                 $attempts = $resourcetracker{$symb."\0".$part."\0attempts"};      foreach my $part (@parts) {
             }          if ($resource->handgrade($part) eq 'yes') {
             if (exists($resourcetracker{$symb."\0".$part."\0users"})) {              next;
                 $users = $resourcetracker{$symb."\0".$part."\0users"};          }
             }          if ($resource->is_survey($part)) {
             if (exists($resourcetracker{$symb."\0".$part."\0correct"})) {              next;
                 $corrects = $resourcetracker{$symb."\0".$part."\0correct"};          }
             }          %{$stats{$part}} = ();
             if ($attempts > 0) {          my ($attempts,$users,$corrects,$degdiff,$av_attempts);
                 $degdiff =  1 - ($corrects/$attempts);          if (exists($$resourcetracker{$symb."\0".$part."\0attempts"})) {
                 $degdiff = sprintf("%.2f",$degdiff);              $attempts = $$resourcetracker{$symb."\0".$part."\0attempts"};
             }          }
             if ($users > 0) {          if (exists($$resourcetracker{$symb."\0".$part."\0users"})) {
                 $av_attempts = $attempts/$users;              $users = $$resourcetracker{$symb."\0".$part."\0users"};
                 $av_attempts = sprintf("%.2f",$av_attempts);          }
             }          if (exists($$resourcetracker{$symb."\0".$part."\0correct"})) {
             if ((($degdiff ne '' && $degdiff >= $$threshold{'degdiff'}) || ($av_attempts ne '' && $av_attempts >= $$threshold{'av_attempts'})) && ($users >= $$threshold{'numstudents'})) {              $corrects = $$resourcetracker{$symb."\0".$part."\0correct"};
                 $stats{$part}{degdiff} = $degdiff;          }
                 $stats{$part}{attempts} = $av_attempts;          if ($attempts > 0) {
                 $stats{$part}{users} = $users;              $degdiff =  1 - ($corrects/$attempts);
  $lastreset{$part} = $resourcetracker{$symb."\0".$part."\0resettime"};              $degdiff = sprintf("%.2f",$degdiff);
                 $warning = 1;          }
             }          if ($users > 0) {
         }              $av_attempts = $attempts/$users;
         if ($warning) {              $av_attempts = sprintf("%.2f",$av_attempts);
             if ($warningnum %2 == 1) {          }
                 $rowColor = $rowColor1;          if ((($degdiff ne '' && $degdiff >= $$threshold{'degdiff'}) || ($av_attempts ne '' && $av_attempts >= $$threshold{'av_attempts'})) && ($users >= $$threshold{'numstudents'})) {
             } else {              $stats{$part}{degdiff} = $degdiff;
                 $rowColor = $rowColor2;              $stats{$part}{attempts} = $av_attempts;
               $stats{$part}{users} = $users;
               $lastreset{$part} = $$resourcetracker{$symb."\0".$part."\0resettime"};
               if ($lastreset{$part}) {
                   $lastreset{$part} = &Apache::lonnavmaps::timeToHumanString($lastreset{$part});
             }              }
             $$triggered{$symb}{title} = $resource->title;              $warning = 1;
             foreach my $part (@parts) {          }
                 if (exists($stats{$part}{users})) {      }
                     my $resetname = 'reset_'.&Apache::lonnet::escape($symb."\0".$part);      if ($warning) {
                     my $resettitle = 'title_'.&Apache::lonnet::escape($symb."\0".$part);          $$triggered{$symb}{title} = $resource->title;
                     if ($$triggered{$symb}{numparts}) {          my $partcount = 0;
                         $$triggered{$symb}{text} .= '<tr bgcolor="'.$rowColor.'">'."\n";          @{$$triggered{$symb}{text}} = ();
                     }          foreach my $part (@parts) {
                     if (@parts > 1) {              if (exists($stats{$part}{users})) {
                         $$triggered{$symb}{text} .= '                  my $resetname = 'reset_'.&escape($symb."\0".$part);
                          <td align="right"><small>part - '.$part.'<small></td>';                  my $resettitle = 'title_'.&escape($symb."\0".$part);
                     } else {                  if (@parts > 1) {
                         $$triggered{$symb}{text} .= '                      $$triggered{$symb}{text}[$partcount] = '
                          <td align="right"><small>single part</small></td>';                       <td>'.&mt('part - ').$part.'</td>';
                     }                  } else {
                     $$triggered{$symb}{text} .= '                      $$triggered{$symb}{text}[$partcount] = '
                          <td align="right"><small>'.$stats{$part}{users}.'</small></td>                       <td>'.&mt('single part').'</td>';
                          <td align="right"><small>'.$stats{$part}{attempts}.'</small></td>  
                          <td align="right"><small>'.$stats{$part}{degdiff}.'</small></td>  
                          <td align="right"><small>'.$lastreset{$part}.'</small></td>  
                          <td align="right"><small><input type="checkbox" name="'.$resetname.'" /><input type="hidden" name="'.$resettitle.'" value="'.&Apache::lonnet::escape($$triggered{$symb}{title}).'" /></td>   
                         </tr>';  
                     $$triggered{$symb}{numparts} ++;  
                 }                  }
                   $$triggered{$symb}{text}[$partcount] .= '
                        <td>'.$stats{$part}{users}.'</td>
                        <td>'.$stats{$part}{attempts}.'</td>
                        <td>'.$stats{$part}{degdiff}.'</td>
                        <td>'.$lastreset{$part}.'</td>
                        <td><input type="checkbox" name="'.$resetname.'" /><input type="hidden" name="'.$resettitle.'" value="'.&escape($$triggered{$symb}{title}).'" /></td>';
                   $partcount ++;
             }              }
             push(@{$warnings},$symb);              $$triggered{$symb}{numparts} = $partcount;
             $warningnum ++;  
         }          }
           push(@{$warnings},$symb);
     }      }
 }  }
   
   
 sub get_curr_thresholds {  sub get_curr_thresholds {
     my ($threshold,$cdom,$crs) = @_;      my ($threshold,$uname,$udom,$cid,$cdom,$crs) = @_;
     my %coursesettings = &Apache::lonnet::dump('environment',      # set default values
                                      $cdom,$crs,'internal.threshold');      %$threshold = (av_attempts => 2,
     if (exists($coursesettings{'internal.threshold_av_attempts'})) {                    degdiff => 0.5,
         $$threshold{'av_attempts'} = $coursesettings{'internal.threshold_av_attempts'};                    numstudents => 2
                     );
       my %thresholdsettings = &Apache::lonnet::dump('nohist_whatsnew',$udom,
                                                        $uname,$cid.':threshold');
       my $thresholdcount = 0;
       my ($tmp) = %thresholdsettings;
       unless ($tmp =~ /^(con_lost|error|no_such_host)/i) {
           foreach my $item (keys %{$threshold}) { 
               if (exists($thresholdsettings{$cid.':threshold_'.$item})) {
                   $$threshold{$item} = 
                                $thresholdsettings{$cid.':threshold_'.$item};
                   $thresholdcount ++;
               }
           }
     }      }
     if (exists($coursesettings{'internal.threshold_degdiff'})) {      if ($thresholdcount == 3) {
         $$threshold{'degdiff'} = $coursesettings{'internal.threshold_degdiff'};          return;
     }      }
     if (exists($coursesettings{'internal.threshold_numstudents'})) {      my %coursesettings = &Apache::lonnet::dump('environment',
         $$threshold{'numstudents'} = $coursesettings{'internal.threshold_numstudents'};                                                $cdom,$crs,'internal.threshold');
       my ($temp) = %coursesettings;
       unless ($temp =~ /^(con_lost|error|no_such_host)/i) {  
           foreach my $item (keys %{$threshold}) {
               unless (exists($thresholdsettings{$cid.':threshold_'.$item})) {
                   if (exists($coursesettings{'internal.threshold_'.$item})) {
                       $$threshold{$item} = 
                                $coursesettings{'internal.threshold_'.$item};
                   }
               }
           }
     }      }
       return;
   }
   
   sub get_current {
       my ($uname,$udom,$cid,$caller) = @_;
       my $currvalue;
       my %settings = &Apache::lonnet::dump('nohist_whatsnew',$udom,$uname,$cid.
                                                                   ':'.$caller);
       my ($tmp) = %settings;
       unless ($tmp =~ /^(con_lost|error|no_such_host)/i) {
           $currvalue = $settings{$cid.':'.$caller};
       }
       return $currvalue;
 }  }
   
 sub process_reset {  sub process_reset {
     my ($dom,$crs) = @_;      my ($dom,$crs) = @_;
     my $result = '<b>Counters reset for following problems (and parts):</b><br />';      my $result = '<b>'.&mt('Counters reset for following problems (and parts):').
                              '</b><br />';
     my @agg_types = ('attempts','users','correct');      my @agg_types = ('attempts','users','correct');
     my %agg_titles = (      my %agg_titles = &Apache::lonlocal::texthash (
                      attempts => 'Number of submissions',                       attempts => 'Number of submissions',
                      users => 'Students with submissions',                       users => 'Students with submissions',
                      correct => 'Number of correct submissions',                       correct => 'Number of correct submissions',
Line 697  sub process_reset { Line 1096  sub process_reset {
     my %titles = ();      my %titles = ();
     foreach my $key (keys(%env)) {      foreach my $key (keys(%env)) {
         next if ($key !~ /^form\.reset_(.+)$/);          next if ($key !~ /^form\.reset_(.+)$/);
         my $title = &Apache::lonnet::unescape($env{'form.title_'.$1});          my $title = &unescape($env{'form.title_'.$1});
         my $reset_item = &Apache::lonnet::unescape($1);          my $reset_item = &unescape($1);
         my %curr_aggregates = &Apache::lonnet::dump('nohist_resourcetracker',$dom,$crs,$reset_item);          my %curr_aggregates = &Apache::lonnet::dump('nohist_resourcetracker',$dom,$crs,$reset_item);
         my %aggregates = ();          my %aggregates = ();
         my ($symb,$part) = split(/\0/,$reset_item);          my ($symb,$part) = split(/\0/,$reset_item);
Line 724  sub process_reset { Line 1123  sub process_reset {
 }  }
   
 sub process_update {  sub process_update {
     my ($dom,$crs,$threshold_titles) = @_;      my ($uname,$udom,$threshold_titles) = @_;
     my $setoutput = '<b>Changes to threshold(s) for problem tracking:</b><br />';      my $setoutput = '<b>'.&mt('Changes to threshold(s) for problem tracking:').'</b><br />';
     foreach (keys %env) {      foreach (keys %env) {
         next if ($_!~/^form\.(.+)\_setparmval$/);          next if ($_!~/^form\.(.+)\_setparmval$/);
         my $name  = $1;          my $name  = $1;
         my $value = $env{'form.'.$name.'_value'};          my $value = $env{'form.'.$name.'_value'};
         if ($name && defined($value)) {          if ($name && defined($value) && ($value ne '')) {
             my $put_result = &Apache::lonnet::put('environment',              my $put_result = &Apache::lonnet::put('nohist_whatsnew',
                                                   {$name=>$value},$dom,$crs);                                                    {$name=>$value},$udom,$uname);
                         
             my ($shortname) = ($name =~ /^internal\.threshold_(.+)$/);               my ($shortname) = ($name =~ /^\Q$env{'request.course.id'}\E:threshold_(.+)$/);
             if ($put_result eq 'ok') {              if ($put_result eq 'ok') {
                 $setoutput.=&mt('Set threshold for [_1] to [_2]',                  $setoutput.=&mt('Set threshold for [_1] to [_2]',
  '<b>'.$$threshold_titles{$shortname}.'</b>',   '<b>'.$$threshold_titles{$shortname}.'</b>',
Line 749  sub process_update { Line 1148  sub process_update {
     return $setoutput;      return $setoutput;
 }  }
   
 sub getmail {  sub getnormalmail {
     my ($newmsgs,$critmsgs) = @_;      my ($newmsgs) = @_;
 # Check for unread mail in course  # Check for unread mail in course
     my $msgcount = 0;      my $msgcount = 0;
   
     my @messages = sort(&Apache::lonnet::getkeys('nohist_email'));      my @messages = sort(&Apache::lonnet::getkeys('nohist_email'));
     foreach my $message (@messages) {      foreach my $message (@messages) {
  my $msgid=&Apache::lonnet::escape($message);   my $msgid=&escape($message);
         my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)=          my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)=
             &Apache::lonmsg::unpackmsgid($msgid);              &Apache::lonmsg::unpackmsgid($msgid);
         if (($fromcid) && ($fromcid eq $env{'request.course.id'})) {          if (($fromcid) && ($fromcid eq $env{'request.course.id'})) {
             if (defined($sendtime) && $sendtime!~/error/) {              if (defined($sendtime) && $sendtime!~/error/) {
                 my $numsendtime = $sendtime;                  my $numsendtime = $sendtime;
                 $sendtime = &Apache::lonlocal::locallocaltime($sendtime);  
                 if ($status eq 'new') {                  if ($status eq 'new') {
                     $msgcount ++;                  $sendtime = &Apache::lonlocal::locallocaltime($sendtime);
       $msgcount ++;
                     if ($shortsubj eq '') {                      if ($shortsubj eq '') {
                         $shortsubj = &mt('No subject');                          $shortsubj = &mt('No subject');
                     }                      }
                     $shortsubj = &Apache::lonnet::unescape($shortsubj);  
                     push(@{$newmsgs}, {                      push(@{$newmsgs}, {
                         msgid    => $msgid,                          msgid    => $msgid,
                         sendtime => $sendtime,                          sendtime => $sendtime,
Line 780  sub getmail { Line 1178  sub getmail {
             }              }
         }          }
     }      }
       return $msgcount;
   }
   
   sub getcritmail {
       my ($critmsgs) = @_; 
 # Check for critical messages in course  # Check for critical messages in course
     my %what=&Apache::lonnet::dump('critical');      my %what=&Apache::lonnet::dump('critical');
     my $result = '';      my $result = '';
Line 796  sub getmail { Line 1198  sub getmail {
                 if ($shortsubj eq '') {                  if ($shortsubj eq '') {
                     $shortsubj = &mt('No subject');                      $shortsubj = &mt('No subject');
                 }                  }
                 $shortsubj = &Apache::lonnet::unescape($shortsubj);  
                 push(@{$critmsgs}, {                  push(@{$critmsgs}, {
                         msgid    => $msgid,                          msgid    => $msgid,
                         sendtime => $sendtime,                          sendtime => $sendtime,
Line 807  sub getmail { Line 1208  sub getmail {
             }              }
         }          }
     }      }
     return ($msgcount,$critmsgcount);      return $critmsgcount;
   }
   
   sub getexpired {
       my ($rolechgs,$rolechgtime,$status) = @_;
       my $expirecount = &getrolechanges($rolechgs,$rolechgtime,$status);
       return $expirecount;
   }
   
   sub getactivated {
       my ($rolechgs,$rolechgtime,$status) = @_;
       my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
       my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
       my $now = time();
       my $context = 'course';
       my ($permission,$allowed) =
           &Apache::lonuserutils::get_permission($context);
       my $viewablesec = &Apache::lonuserutils::viewable_section($permission);
       my %changes=&Apache::lonnet::dump('nohist_rolelog',$cdom,$cnum);
       my (%stucounted,%advcounted);
       my $activatedcount = 0;
       if (keys(%changes) > 0) {
           foreach my $chg (sort { $b <=> $a } (keys(%changes))) {
               if (ref($changes{$chg}) eq 'HASH') {
                   my $timestamp = $changes{$chg}{'exe_time'};
                   if ($timestamp) {
                       if ($rolechgtime > 0) {
                           if ($timestamp < $rolechgtime) {
                               last;
                           }
                       }
                       if (ref($changes{$chg}{'logentry'}) eq 'HASH') {
                           next if ($changes{$chg}{'delflag'});
                           my $start = $changes{$chg}{'logentry'}{'start'};
                           my $end = $changes{$chg}{'logentry'}{'end'};
                           my $section = $changes{$chg}{'logentry'}{'section'};
                           my $role = $changes{$chg}{'logentry'}{'role'};
                           my $uname = $changes{$chg}{'uname'};
                           my $udom = $changes{$chg}{'udom'};
                           next if ($end && $end <= $now);
                           if (($viewablesec ne '') && ($section ne '')) {
                               next if ($viewablesec ne $section);
                           }
                           next if ($start >= $timestamp);
                           if ($role eq 'st') {
                               $stucounted{$uname.':'.$udom.':'.$section} = $start.':'.$end;
                           } else {
                               $advcounted{$uname.':'.$udom.':'.$role.':'.$section} = $start.':'.$end;
                           }
                           my %chginfo = (
                                          'section' => $section,
                                          'uname'   => $uname,
                                          'udom'    => $udom,
                                          'role'    => $role,
                                          'status'  => $status,
                           );
                           $activatedcount ++;
                           push (@{$rolechgs->{$timestamp}},\%chginfo);
                       }
                   }
               }
           }
       }
       $activatedcount += &getrolechanges($rolechgs,$rolechgtime,$status,\%stucounted,\%advcounted);
       return $activatedcount;
   }
   
   sub getrolechanges {
       my ($rolechgs,$rolechgtime,$status,$stucountref,$advcountref) = @_;
       my (%stucounted,%advcounted);
       if (ref($stucountref) eq 'HASH') {
           %stucounted = %{$stucountref};
       }
       if (ref($advcountref) eq 'HASH') {
           %advcounted = %{$advcountref};
       }
       my $withsec = 1;
       my $hidepriv = 1;
       my $context = 'course';
       my @statuses = ($status);
       my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
       my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
       my $now = time();
       my ($permission,$allowed) =
           &Apache::lonuserutils::get_permission($context);
       my $viewablesec = &Apache::lonuserutils::viewable_section($permission);
       my $classlist = &Apache::loncoursedata::get_classlist();
       my $secidx = &Apache::loncoursedata::CL_SECTION();
       my $startidx = &Apache::loncoursedata::CL_START();
       my $endidx = &Apache::loncoursedata::CL_END();
       my $rolechgcount = 0;
       foreach my $key (keys(%{$classlist})) {
           my ($userstatus,$eventtime);   
           my $student = $classlist->{$key};
           if (ref($student) eq 'ARRAY') {
               my $start = $student->[$startidx];
               my $end = $student->[$endidx];
               my $sec = $student->[$secidx]; 
               my ($stuname,$studom) = split(/:/,$key);
               if ($status eq 'active') {
                   if (exists($stucounted{$key.':'.$sec})) {
                       next;
                   }
               }
               if (($end == 0) || ($end > $start)) {
                   if ($start <= $now) {
                       if ($end && $end < $now) {
                           if ($rolechgtime > 0) {
                               if ($end > $rolechgtime) {
                                   $userstatus = 'previous';
                               }
                           } else {
                               $userstatus = 'previous';
                           }
                       } else {
                           if ($rolechgtime > 0) {
                               if ($start >= $rolechgtime) {
                                   $userstatus = 'active';
                               }
                           } else {
                               $userstatus = 'active';
                           }
                       }
                   }
               }
               next if ($userstatus ne $status);
               if ($status eq 'active') {
                   $eventtime = $start;
               } else {
                   $eventtime = $end;
               }
               if (($viewablesec ne '') && ($sec ne '')) {
                   next if ($viewablesec ne $sec);
               }
               my %chginfo = (
                               'section' => $sec,
                               'uname'   => $stuname,
                               'udom'    => $studom,
                               'role'    => 'st', 
                               'status'  => $userstatus,
                             );
               $rolechgcount ++;
               push (@{$rolechgs->{$eventtime}},\%chginfo);
           }
       }
       my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
                                 \@statuses,undef,undef,$withsec,$hidepriv);
       foreach my $item (keys(%advrolehash)) {
           my ($userstatus,$eventtime);
           my ($uname,$udom,$role,$section) = split(/:/,$item,-1);
           my ($start,$end) = split(/:/,$advrolehash{$item});
           if ($start eq '-1' && $end eq '-1') {
               next;
           } else {
               if ($status eq 'active') {
                   if (exists($advcounted{$item})) {
                       next;
                   }
               }
               if (($end == 0) || ($end > $start)) {
                   if ($start <= $now) {
                       if ($end && $end < $now) {
                           if ($rolechgtime > 0) {
                               if ($end > $rolechgtime) {
                                   $userstatus = 'previous';
                               }
                           } else {
                               $userstatus = 'previous';
                           }
                       } else {
                           if ($rolechgtime > 0) {
                               if ($start >= $rolechgtime) {
                                   $userstatus = 'active';
                               }
                           } else {
                               $userstatus = 'active';
                           }
                       }
                   }
               }
               next if ($userstatus ne $status);
               if ($status eq 'active') {
                   $eventtime = $start;
               } else {
                   $eventtime = $end;
               }
           }
           if (($viewablesec ne '') && ($section ne '')) {
               next if ($viewablesec ne $section);
           }
           my %chginfo = ( 
                           'section' => $section,
                           'uname'   => $uname,
                           'udom'    => $udom,
                           'role'    => $role,
                           'status'  => $userstatus,    
                         );
           $rolechgcount ++; 
           push (@{$rolechgs->{$eventtime}},\%chginfo); 
       }
       return $rolechgcount;
   }
   
   sub checkversions {
       my ($cdom,$crs,$navmap,$changed,$starttime) = @_;
       my %changes=&Apache::lonnet::dump('versionupdate',$cdom,$crs);
       my ($tmp) = keys(%changes);
       unless ($tmp =~ /^(con_lost|error|no_such_host)/i) {
           if (keys(%changes) > 0) {
               foreach my $key (sort(keys(%changes))) {
                   if ($changes{$key} > $starttime) {
                       my $version;
                       my ($root,$extension)=($key=~/^(.*)\.(\w+)$/);
                       my $currentversion=&Apache::lonnet::getversion($key);
                       my $revdate = 
                             &Apache::lonnet::metadata($root.'.'.$extension,
                                                        'lastrevisiondate');
                       $revdate =  &Apache::lonlocal::locallocaltime($revdate);
                       my $linkurl=&Apache::lonnet::clutter($key);
                       my $usedversion=$navmap->usedVersion('version_'.$linkurl);
                       my @resources = $navmap->getResourceByUrl($linkurl,1);
                       if (($usedversion) && ($usedversion ne 'mostrecent')) {
                           $version = $usedversion;     
                       } else {
                           $version = $currentversion;
                       }
                       foreach my $res (@resources) {
                            if (ref($res) eq 'Apache::lonnavmaps::resource') { 
                               my $symb = $res->symb();
                               %{$$changed{$symb}} = (
                                                   current => $currentversion,
                                                   version => $version,
                                                   revdate => $revdate,
                               );
                           }
                       }
                   }
               }
           }
       }
       return;
   }
   
   sub display_handgrade {
       my ($r,$tograde,$ungraded,$itemserror) = @_;
       my %lt = &Apache::lonlocal::texthash(
                           'prna' => 'Problem Name',
                           'nmun' => 'Number ungraded',
                           'nopr' => 'No problems require handgrading',
       );
       if (@{$tograde} > 0) {
           $r->print('<tr class="LC_info_row"><td class="LC_left_item">'.
                     $lt{'prna'}.'</td><td class="LC_right_item">'.
                     $lt{'nmun'}.'</td></tr>');
           my $rowNum = 0;
           foreach my $res (@{$tograde}) {
               $rowNum ++;
               my $css_class = $rowNum%2?' class="LC_odd_row"':'';
               my ($map,$id,$url)=&Apache::lonnet::decode_symb($res);
               my $linkurl=&Apache::lonnet::clutter($url);
               $linkurl .= '?symb='.&escape($res);
               if ($$ungraded{$res}{'enclink'}) {
                   $linkurl = 
                       $$ungraded{$res}{'enclink'}.'?symb='.$$ungraded{$res}{'encsymb'};
               } 
               $r->print('<tr'.$css_class.'><td><a href="'.$linkurl.'">'.$$ungraded{$res}{title}.'</a></td><td class="LC_right_item">'.$$ungraded{$res}{count}.'</td></tr>');
           }
       } elsif ($itemserror) {
           $r->print('<tr class="LC_empty_row"><td>'.$itemserror.'</td></tr>');
       } else {
           $r->print('<tr class="LC_empty_row"><td>'.$lt{'nopr'}.'</td></tr>');
       }
   }
   
   sub display_haserrors {
       my ($r,$bombs,$bombed,$res_title,$itemserror) = @_;
       my $bombnum = 0;
       my %lt = &Apache::lonlocal::texthash(
                                      reso => 'Resource',
                                      nmer => 'Number of errors',
                                      noer => 'No problems with errors',
       );
       if (@{$bombs} > 0) {
           $r->print('<tr class="LC_info_row"><td class="LC_left_item">'.
                     $lt{'reso'}.'</td><td class="LC_right_item">'.
                     $lt{'nmer'}.'</td></tr>');
           @{$bombs} = sort { &cmp_title($a,$b,$res_title) } @{$bombs};
           foreach my $bomb (@{$bombs}) {
               $bombnum ++;
               my $css_class = $bombnum%2?' class="LC_odd_row"':'';
               $r->print('<tr'.$css_class.'><td>'.$$bombed{$bomb}{errorlink}.
                         '</td><td class="LC_right_item">'.
                         $$bombed{$bomb}{errorcount}.'</td></tr>');
           }
       } elsif ($itemserror) {
           $r->print('<tr class="LC_empty_row"><td>'.$itemserror.'</td></tr>');
       } else {
           $r->print('<tr class="LC_empty_row"><td>'.$lt{'noer'}.'</td></tr>');
       }
       return;
   }
   
   sub display_abovethreshold {
       my ($r,$refpage,$warnings,$triggered,$res_title,$itemserror) = @_;
       my %lt = &Apache::lonlocal::texthash(
                    reso => 'Resource',
                    part => 'Part',
                    nust => 'Num. students',
                    avat => 'Av. Attempts',
                    dedi => 'Deg. Diff',
                    lare => 'Last Reset',
                    reco => 'Reset Count?',
                    rese => 'Reset counters to 0',
                    nopr => 'No problems satisfy threshold criteria',
       );
       if (@{$warnings} > 0) {
           @{$warnings} = sort { &cmp_title($a,$b,$res_title) } @{$warnings};
           $r->print('<form name="reset_tracking" method="post" action="/adm/whatsnew">'.
                   ' <input type="hidden" name="command" value="reset" />'."\n".
                   ' <input type="hidden" name="refpage" value="'.$refpage.'" />'.
                   "\n");
           $r->print('<tr class="LC_info_row">'.
     '<td class="LC_left_item">'.$lt{'reso'}.'</td>'.
     '<td>'.$lt{'part'}.'</td><td>'.$lt{'nust'}.'</td>'.
     '<td>'.$lt{'avat'}.'</td><td>'.$lt{'dedi'}.'</td>'.
     '<td>'.$lt{'lare'}.'</td><td  class="LC_right_item">'.
                     $lt{'reco'}.'</td></tr>');
    my $row;
           foreach my $res (@{$warnings}) {
       $row++;
               my ($map,$id,$url)=&Apache::lonnet::decode_symb($res);
               my $linkurl=&Apache::lonnet::clutter($url);
               my $rowspan;
               if ($$triggered{$res}{numparts} > 1) {
                   $rowspan = 'rowspan="'.$$triggered{$res}{numparts}.'"';
               }
               $linkurl .= '?symb='.&escape($res);
               if ($$triggered{$res}{'enclink'}) {
                   $linkurl = 
                     $$triggered{$res}{'enclink'}.'?symb='.$$triggered{$res}{'encsymb'};
               }
               my $css_class = $row%2?' class="LC_odd_row"':'';
               $r->print('<tr'.$css_class.'>'.
         '<td class="LC_first_item" '.$rowspan.'><a href="'.$linkurl.'">'.
         $$triggered{$res}{title}.'</a></td>');
                         if (ref($$triggered{$res}{text}) eq 'ARRAY') {
             $r->print($$triggered{$res}{text}[0]);
                         }
                         $r->print('</tr>');
               if (ref($$triggered{$res}{text}) eq 'ARRAY') {
                   if (@{$$triggered{$res}{text}} > 1) {
                       for (my $i=1; $i<@{$$triggered{$res}{text}}; $i++) {
                           $r->print('<tr class="'.$css_class.'">'.
                                     $$triggered{$res}{text}[$i].'</tr>');
                       }
                   }
               }
           }
           $r->print('<tr class="LC_info_row"><td colspan="7" class="LC_right_item"><br /><input type="submit" name="counters" value="'.$lt{'rese'}.'" /></td></tr></form>');
       } elsif ($itemserror) {
           $r->print('<tr class="LC_empty_row"><td>'.$itemserror.'</td></tr>');
       } else {
           $r->print('<tr class="LC_empty_row"><td>'.$lt{'nopr'}.'</td></tr>');
       }
   }
   
   sub display_versionchanges {
       my ($r,$changed,$res_title,$interval,$itemserror) = @_;
       my %lt = &Apache::lonlocal::texthash(
           'reso' => 'Resource',
           'revd' => 'Last revised',
           'newv' => 'New version',
           'veru' => 'Version used',
       );
       if (keys(%{$changed}) > 0) {
           $r->print('<tr class="LC_info_row"><td class="LC_left_item">'.
                     $lt{'reso'}.'</td><td>'.$lt{'revd'}.'</td><td>'.
                     $lt{'newv'}.'</td><td class="LC_right_item">'.
                     $lt{'veru'}.'</td></tr>');
           my @changes = sort { &cmp_title($a,$b,$res_title) } keys(%{$changed});
           my $changenum = 0;
           foreach my $item (@changes) {
               $changenum ++;
               my $css_class = $changenum%2?' class="LC_odd_row"':'';
               my ($map,$id,$url)=&Apache::lonnet::decode_symb($item);
               my $linkurl=&Apache::lonnet::clutter($url);
               $linkurl .= '?symb='.&escape($item);
   
               $r->print('<tr'.$css_class.'><td><a href="'.$linkurl.'">'.
                         $$res_title{$item}.'</a></td><td>'.
                         $$changed{$item}{'revdate'}.'</td><td>'.
                         $$changed{$item}{'current'}.'</td><td>'.
                         $$changed{$item}{'version'}.'</td></tr>');
           }
       } elsif ($itemserror) {
           $r->print('<tr class="LC_empty_row"><td>'.$itemserror.'</td></tr>');
       } else {
           $r->print('<tr class="LC_empty_row"><td>'
                    .&mt('No '.$interval).'</td></tr>');
       }
       return;
   }
   
   sub display_rolechanges {
       my ($r,$chgcount,$changed,$interval,$crstype) = @_;
       my $now = time();
       my %lt = &Apache::lonlocal::texthash(
           'user'  => 'User',
           'tich'  => 'Time of change',
           'role'  => 'Role',
           'sec'   => 'Section',
           'status'  => 'Status',
       );
       if ($chgcount) {
           $r->print('<tr class="LC_info_row">'.
                     '<td class="LC_left_item">'.$lt{'tich'}.'</td>'.
                     '<td class="LC_left_item">'.$lt{'user'}.'</td>'.
                     '<td class="LC_left_item">'.$lt{'role'}.'</td>'.
                     '<td class="LC_left_item">'.$lt{'sec'}.'</td>'.
                     '<td class="LC_left_item">'.$lt{'status'}.'</td></tr>');
           if (ref($changed) eq 'HASH') {
               my @changes = sort { $b <=> $a } (keys(%{$changed}));
               my $changenum = 0;
               foreach my $item (@changes) {
                   if (ref($changed->{$item}) eq 'ARRAY') {
                       foreach my $chg (@{$changed->{$item}}) {
                           if (ref($chg) eq 'HASH') {
                               my $section;
                               my $role = 
                                   &Apache::lonnet::plaintext($chg->{'role'},$crstype);
                               my $status = &mt($chg->{'status'});
                               if ($chg->{'section'} eq '') {
                                   $section = &mt('none');
                               } else {
                                   $section = $chg->{'section'};
                               }
                               my $uname = $chg->{'uname'};
                               my $udom = $chg->{'udom'};
                               $changenum ++;
                               my $css_class = $changenum%2?' class="LC_odd_row"':'';
                               my $link = 
                                   &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom),$uname,$udom);
                               $r->print('<tr'.$css_class.'>'.
                                         '<td>'.&Apache::lonlocal::locallocaltime($item).'</td>'.
                                         '<td>'.$link.'</td>'.
                                         '<td>'.$role.'</td>'.
                                         '<td>'.$section.'</td>'.
                                         '<td>'.$status.'</td></tr>');
                           }
                       }
                   }
               }
           }
       } else {
           $r->print('<tr class="LC_empty_row"><td>'
                    .&mt('There are no '.$interval).'</td></tr>');
       }
       return;
   }
    
   sub display_coursediscussion {
       my ($r,$newdiscussions,$unread,$countunread,$res_title,$itemserror) = @_;
       my $lctype = lc(&Apache::loncommon::course_type());
       my %lt = &Apache::lonlocal::texthash(
                   'loca' => 'Location',
                   'type' => 'Type',
                   'numn' => 'Number of new posts',
                   'noun' => 'No unread posts in '.$lctype.' discussions',
                   'tmlp' => 'Time of last post', 
       );
       if (@{$newdiscussions} > 0) {
           $r->print('<tr class="LC_info_row"><td class="LC_left_item">'.
                     $lt{'loca'}.'</td><td>'.
                     $lt{'type'}.'</td>');
           if ($countunread eq 'on') {
               $r->print('<td>'.$lt{'tmlp'}.'</td>'.
                         '<td class="LC_right_item">'.$lt{'numn'}.'</td>');
           } else {
               $r->print('<td class="LC_right_item">'.$lt{'tmlp'}.'</td>');
           }
           $r->print("</tr>\n");
           @{$newdiscussions} = sort { &cmp_title($a,$b,$res_title) }
                                                               @{$newdiscussions};
           my $rowNum = 0;
           foreach my $ressymb (@{$newdiscussions}) {
               $rowNum ++;
               my $forum_title = $$unread{$ressymb}{'title'};
               my $type = 'Resource';
               my $feedurl=&Apache::lonfeedback::get_feedurl($ressymb);
               my $disclink = $feedurl.'?symb='.$$unread{$ressymb}{symb};
               if ($feedurl =~ /bulletinboard/) {
                   $type = 'Discussion Board';
               }
               if ($$unread{$ressymb}{'enclink'}) {
                   $disclink = $$unread{$ressymb}{'enclink'}.'?symb='.$$unread{$ressymb}{'encsymb'};
               }
               my $css_class = $rowNum%2?' class="LC_odd_row"':'';
               my $lastpost = &Apache::lonnavmaps::timeToHumanString(
                                                  $$unread{$ressymb}{'lastpost'});
               $r->print('<tr'.$css_class.'><td><a href="'.$disclink.'">'.$forum_title.'</a>&nbsp;</td><td>'.&mt($type).'&nbsp;</td>');
               if ($countunread eq 'on') {
                   my $unreadnum = $$unread{$ressymb}{'unreadcount'};
                   $r->print('<td>'.$lastpost.'</td><td class="LC_right_item">'.
                             $unreadnum.'&nbsp;</td>');
               } else {
                   $r->print('<td class="LC_right_item">'.$lastpost.'</td>');
               }
               $r->print("</tr>\n");
           }
       } elsif ($itemserror) {
           $r->print('<tr class="LC_empty_row"><td>'.$itemserror.'</td></tr>');
       } else {
           $r->print('<tr class="LC_empty_row"><td>'.$lt{'noun'}.'</td></tr>');
       }
   }
   
   sub display_coursenormalmail {
       my ($r,$msgcount,$newmsgs) = @_;
       my $lctype = lc(&Apache::loncommon::course_type());
       if ($msgcount > 0) {
           $r->print('<tr class="LC_info_row"><td class="LC_left_item">'.
                     &mt('Number').'</td><td>'.&mt('Subject').'</td><td>'.
                     &mt('Sender').'</td><td class="LC_right_item">'.
                     &mt('Date/Time').'</td></tr>');
           my $mailcount = 0;
           foreach my $msg (@{$newmsgs}) {
               $mailcount ++;
               my $css_class = $mailcount%2?' class="LC_odd_row"':'';
               $r->print('<tr'.$css_class.'><td>'.$mailcount
                         .'.&nbsp;</td><td><a href="/adm/email?display='
                         .$msg->{'msgid'}.'">'
                         .$msg->{'shortsub'}.'</a>&nbsp;&nbsp;</td><td>&nbsp;'
                         .$msg->{'from'}.':'.$msg->{'fromdom'}.'&nbsp;</td><td>'
                         .$msg->{'sendtime'}.'</td></tr>');
           }
       } else {
           $r->print('<tr class="LC_empty_row"><td>'.
                     &mt('No new '.$lctype.' messages').'</td></tr>');
       }
   }
   
   sub display_coursecritmail {
       my ($r,$critmsgcount,$critmsgs) = @_;
       my $lctype = lc(&Apache::loncommon::course_type());
       if ($critmsgcount > 0) {
           $r->print('<tr class="LC_info_row"><td class="LC_left_item">'.
                     &mt('Number').'</td><td>'.&mt('Subject').'</td><td>'.
                     &mt('Sender').'</td><td class="LC_right_item">'.
                     &mt('Date/Time').'</td></tr>');
           my $mailcount = 0;
           foreach my $msg (@{$critmsgs}) {
               $mailcount ++;
               my $css_class = $mailcount%2?' class="LC_odd_row"':'';
               $r->print('<tr'.$css_class.'><td>'.$mailcount.
                         '. &nbsp;</td><td><a href="/adm/email?folder=critical">'.
                         $msg->{'shortsub'}.'</a>&nbsp; &nbsp;</td><td>&nbsp;'.
                         $msg->{'from'}.':'.$msg->{'fromdom'}.'&nbsp;</td><td>'.
                         $msg->{'sendtime'}.'</td></tr>');
           }
       } else {
           $r->print('<tr class="LC_empty_row"><td>'.
                     &mt('No unread critical messages in '.$lctype).
                     '</td></tr>');
       }
 }  }
   
 sub cmp_title {  sub cmp_title {
Line 818  sub cmp_title { Line 1782  sub cmp_title {
     return $atitle cmp $btitle;      return $atitle cmp $btitle;
 }  }
   
   sub get_display_settings {
       my ($uname,$udom,$cid) = @_;
       my %settings = &Apache::lonnet::dump('nohist_whatsnew',$udom,$uname,$cid); 
       my ($tmp) = keys(%settings);
       if ($tmp=~ /^(con_lost|error|no_such_host)/i) {
           %settings = ();
           unless ($tmp =~ /^error: 2 /) {
       my $lctype = lc(&Apache::loncommon::course_type());
               &Apache::lonnet::logthis('Error retrieving whatsnew settings: '.
               $tmp.' for '.$uname.':'.$udom.' for '.$lctype.': '.$cid);
           }
       }
       return %settings;
   }
   
   sub store_display_settings {
       my ($uname,$udom,$cid,$checkallowed) = @_;
       my %whatsnew_settings;
       my $result;
       foreach my $key (keys(%{$checkallowed})) {
    if ($key =~ /_section$/) { next; }
           if (exists($env{'form.display_'.$key})) {
               unless ($env{'form.display_'.$key} eq '') {
                   $whatsnew_settings{$cid.':'.$key} = $env{'form.display_'.$key};
               }
           }
       }
       if (keys(%whatsnew_settings)) {
           $result = &Apache::lonnet::put('nohist_whatsnew',\%whatsnew_settings,
                                                                    $udom,$uname);
       } else {
           $result = 'ok';
       }
       return $result;
   }
   
   sub store_interval_setting {
       my ($uname,$udom,$cid,$interval_titles) = @_;
       my %interval_settings = ();
       my $result;
       my $context = $env{'form.intervaltype'};
       if ($env{'form.interval'} ne '') {
           if ($context eq 'oldroles') {
               $interval_settings{$cid.':oldroleinterval'} = $env{'form.interval'};
           } elsif ($context eq 'newroles') {
               $interval_settings{$cid.':newroleinterval'} = $env{'form.interval'};
           } else {
               $interval_settings{$cid.':interval'} = $env{'form.interval'};
           }
           my $outcome = &Apache::lonnet::put('nohist_whatsnew',
                                                \%interval_settings,$udom,$uname);
           if ($outcome eq 'ok') {
               if (ref($interval_titles->{$context}) eq 'HASH') {
                   $result = &mt('New filter setting: [_1].','<b>'. 
                                 $interval_titles->{$context}->{$env{'form.interval'}}.'</b>').'<br />';
               }
           } else {
       my $lctype = lc(&Apache::loncommon::course_type());
               &Apache::lonnet::logthis('Error saving whatsnew '.$context.' interval setting'.
                   ' '.$outcome.' for '.$uname.':'.$udom.' in '.$lctype.' '.$cid);
               $result = &mt('Unable to set interval to [_1] due to [_2].',
                            '<b>'.$interval_titles->{$context}->{$env{'form.interval'}}.'</b>',
                            '<tt>'.$outcome.'</tt>.<br />');
           }
       }
       return $result;
   }
   
   sub store_discussion_setting {
       my ($uname,$udom,$cid) = @_;
       my %discussion_settings;
       my $result;
       if (defined($env{'form.countunread'})) {
           $discussion_settings{$cid.':countunread'} = $env{'form.countunread'};
           my $outcome = &Apache::lonnet::put('nohist_whatsnew',
                                                \%discussion_settings,$udom,$uname);
           if ($outcome eq 'ok') {
               $result = &mt('Count unread posts in discussions display set to [_1]',
                     '<b>'.&mt($env{'form.countunread'}).'</b>').'<br />';
                                                                                     
           } else {
       my $lctype = lc(&Apache::loncommon::course_type());
               &Apache::lonnet::logthis('Error saving whatsnew countunread setting'.
                   ' '.$outcome.' for '.$uname.':'.$udom.' in '.$lctype.' '.$cid);
               $result = &mt('Unable to set "number unread posts display" to [_1]'.
                             ' due to [_2].',
                            '<b>'.&mt($env{'form.countunread'}).'</b>',
                            '<tt>'.$outcome.'</tt>.<br />');
           }
       }
       return $result;
   }
   
   sub store_courseinit_setting {
       my ($uname,$udom,$cid,$initpage) = @_;
       my %courseinit_settings;
       my $page_control;
       my $result;
       if (defined($env{'form.courseinit_control'})) {
           if ($env{'form.courseinit_control'} eq 'userpref') {
               $courseinit_settings{$cid.':courseinit'} = '';
               $page_control = 'global preferences';
           } else {
               if (defined($env{'form.courseinit_page'})) {
                   $courseinit_settings{$cid.':courseinit'} = 
                                                     $env{'form.courseinit_page'};
                   $page_control = 'course specific setting';
               }
           }
           if ($page_control) {
       my $lctype = lc(&Apache::loncommon::course_type());
               my $outcome = &Apache::lonnet::put('nohist_whatsnew',
                                              \%courseinit_settings,$udom,$uname);
               if ($outcome eq 'ok') {
                   if ($page_control eq 'global preferences') {
                       $result = &mt("Page displayed after role selection in $lctype now set by [_1]user's global preferences[_2].",'<b>','</b>');
                   } else {
                       $result = &mt('Page displayed after role selection in this '.$lctype.' set to [_1].'
                                    ,'<b>'.$$initpage{$env{'form.courseinit_page'}}.'</b>');
                   }
               } else {
                   &Apache::lonnet::logthis('Error saving whatsnew courseinit '.
                                            'setting: '.$outcome.' for '.$uname.
                                            ':'.$udom.' in '.$lctype.' '.$cid);
                   if ($page_control eq 'global preferences') {
                       $result = &mt('Unable to set control of page display to [_1]'.
                             ' due to [_2].',
                            '<b>'.$page_control.'</b>',
                            '<tt>'.$outcome.'</tt>.<br />');
                   } else {
                       $result = &mt('Unable to set page display, after role selection, for this '.$lctype.' to [_1] due to [_2].'
                                    ,'<b>'.$$initpage{$env{'form.courseinit_page'}}.'</b>'
                                    ,'<tt>'.$outcome.'</tt>')
                                .'<br />';
                   }
               }
           }
       }
       return $result;
   }
   
   sub start_box {
       my ($r,$show,$heading,$caller,$refpage) = @_;
       my %lt = &Apache::lonlocal::texthash( 
                          chth => 'Change thresholds?',
                          chin => 'Change interval?',
                          chop => 'Change options?',
       );
       my $showhide;
       if ($$show{$caller}) {
           $showhide = '<b><a href="javascript:change_display(document.visible.'.
                                  'display_'.$caller.",'hide'".');">'.
                                  &mt('Hide').'</a></b>';
      
       } else {
           $showhide = '<b><a href="javascript:change_display(document.visible.'.
                                  'display_'.$caller.",'show'".');">'.
                                  &mt('Show').'</a></b>';
       }
       
       $r->print('
            <table class="LC_nested_outer">
             <tr>
              <th class="LC_left_item">'.$$heading{$caller}.'</th>
              <th class="LC_right_item">'.$showhide.'</th>
             </tr>');
        if (($caller eq 'abovethreshold') && ($$show{$caller})) {
            if ($$show{$caller}) {
                $r->print('
                 <tr>
                   <td class="LC_subheader" colspan="2"><a href="/adm/whatsnew?command=chgthreshold&refpage='.$refpage.'">'.$lt{'chth'}.'</a></td>
                 </tr>');
            }
        } elsif (($caller eq 'versionchanges') && ($$show{$caller})) {
            if ($$show{$caller}) {
                $r->print('
                 <tr>
                   <td class="LC_subheader" colspan="2"><a href="/adm/whatsnew?command=chginterval&refpage='.$refpage.'">'.$lt{'chin'}.'</a></td>
                 </tr>');
            }
        } elsif ($caller eq 'coursediscussion') {
            if ($$show{$caller}) {
                $r->print('
                 <tr>
                   <td class="LC_subheader" colspan="2"><a href="/adm/whatsnew?command=chgdisc&refpage='.$refpage.'">'.$lt{'chop'}.'</a></td>
                 </tr>');
            }
        } elsif (($caller eq 'newroles') && ($$show{$caller})) {
            if ($$show{$caller}) {
                $r->print('
                 <tr>
                   <td class="LC_subheader" colspan="2"><a href="/adm/whatsnew?command=chgnewroleinterval&refpage='.$refpage.'">'.$lt{'chin'}.'</a></td>
                 </tr>');
            }
        } elsif (($caller eq 'oldroles') && ($$show{$caller})) {
            if ($$show{$caller}) {
                $r->print('
                 <tr>
                   <td class="LC_subheader" colspan="2"><a href="/adm/whatsnew?command=chgoldroleinterval&refpage='.$refpage.'">'.$lt{'chin'}.'</a></td>
                 </tr>');
            }
        }
       $r->print('
                 <tr>
                  <td colspan="2">
                   <table class="LC_nested">
   ');
       return;
   }
   
   sub end_box {
       my ($r) = shift;
       $r->print('
      </table>
     </td>
    </tr>
   </table><br />');
       return;
   }
   
 1;  1;

Removed from v.1.18  
changed lines
  Added in v.1.95


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.