[LON-CAPA-cvs] cvs: loncom /interface lonwhatsnew.pm

raeburn lon-capa-cvs@mail.lon-capa.org
Fri, 02 Dec 2005 23:17:47 -0000


This is a MIME encoded message

--raeburn1133565467
Content-Type: text/plain

raeburn		Fri Dec  2 18:17:47 2005 EDT

  Modified files:              
    /loncom/interface	lonwhatsnew.pm 
  Log:
  Working on bugs 4240 and 4389.  Streamlining of display building code. Visibility of different components now based on individual privileges.  Infrastructure added for show/hide of individual components. Display of resources with version changes added. Handgraded check uses grading queue. A few small pieces left to do prior to testing.   
  
  
--raeburn1133565467
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20051202181747.txt"

Index: loncom/interface/lonwhatsnew.pm
diff -u loncom/interface/lonwhatsnew.pm:1.32 loncom/interface/lonwhatsnew.pm:1.33
--- loncom/interface/lonwhatsnew.pm:1.32	Mon Oct 10 09:36:35 2005
+++ loncom/interface/lonwhatsnew.pm	Fri Dec  2 18:17:47 2005
@@ -1,5 +1,5 @@
 #
-# $Id: lonwhatsnew.pm,v 1.32 2005/10/10 13:36:35 raeburn Exp $
+# $Id: lonwhatsnew.pm,v 1.33 2005/12/02 23:17:47 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -65,15 +65,15 @@
 
     &Apache::loncommon::content_type($r,'text/html');
     $r->send_http_header;
-    $r->print(&display_header());
-    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";
+    $r->print(&display_header($command));
+    if (! (($env{'request.course.fn'}) && (&Apache::lonnet::allowed('bre',$env{'request.course.id'})))) {
+        # Not in a course, or not allowed to view action items
+        $env{'user.error.msg'}="/adm/whatsnew:bre:0:0:Cannot display what's new screen";
         return HTTP_NOT_ACCEPTABLE;
     }
 
     &Apache::lonhtmlcommon::clear_breadcrumbs();
-    if ($command eq 'chgthreshold') {
+    if (($command eq 'chgthreshold') && (&Apache::lonnet::allowed('vgr',$env{'request.course.id'}))) {
         &Apache::lonhtmlcommon::add_breadcrumb
             ({href=>'/adm/whatsnew?command=threshold',
               text=>"Change thresholds"});
@@ -110,7 +110,7 @@
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
 
-    if ($command eq 'chgthreshold') {
+    if (($command eq 'chgthreshold') && (&Apache::lonnet::allowed('vgr',$env{'request.course.id'}))) {
         &display_config_box($r,$command,$tabbg,\%threshold_titles,$cdom,$crs);
     } else {
         &display_actions_box($r,$command,\%threshold_titles,$cdom,$crs);
@@ -155,19 +155,25 @@
 
     my $rowColor1 = "#ffffff";
     my $rowColor2 = "#eeeeee";
-    my $rowColor;
 
     my %unread = ();
     my %ungraded = ();
     my %bombed = ();
     my %triggered = ();
+    my %changed = ();
     my @newmsgs = ();
     my @critmsgs = ();
     my @newdiscussions = ();
     my @tograde = ();
     my @bombs = ();
     my @warnings = ();
+    my $msgcount = 0;
+    my $critmsgcount = 0;
+
     my %res_title = ();
+    my %show = ();
+    my $needitems = 0;
+    my $boxcount = 0;
 
     my $domain=&Apache::loncommon::determinedomain();
     my $function;
@@ -191,6 +197,64 @@
         $r->print('<br /><b><center>You are accessing an invalid course.</center></b><br /><br />');
         return;
     }
+
+    my %checkallowed = (
+             coursediscussion => &Apache::lonnet::allowed('pch',$env{'request.course.id'}),
+             handgrading => &Apache::lonnet::allowed('mgr',$env{'request.course.id'}),
+             abovethreshold => &Apache::lonnet::allowed('vgr',$env{'request.course.id'}),
+             haserrors => &Apache::lonnet::allowed('opa',$env{'request.course.id'}),
+             versionchanges => &Apache::lonnet::allowed('opa',$env{'request.course.id'}),
+             coursenormalmail => 1,
+             coursecritmail => 1,
+    );
+
+    my %display_settings = &get_display_settings();
+    my $starttime = 86400;
+    my %intervals = (
+                  all => 'since resource creation',
+                   -1 => 'since start of course',
+              2592000 => 'since last month',
+               604800 => 'since last week',
+                86400 => 'since yesterday',
+    );
+    my $interval = $intervals{$starttime};
+
+    my %headings = &Apache::lonlocal::texthash(
+                coursediscussion =>  'Unread course discussion posts',
+                handgrading =>  'Problems requiring handgrading',
+                haserrors => 'Problems with errors',
+                versionchanges => 'Resources in course with version changes '.$interval,
+                coursenormalmail => 'New course message',
+                coursecritmail => 'New critical messages in course',
+    );
+
+    if ($checkallowed{'abovethreshold'}) {
+        &get_curr_thresholds(\%threshold,$cdom,$crs);
+    }
+
+    $headings{'abovethreshold'} = &mt('Problems with av. attempts').' &ge; '.$threshold{'av_attempts'}.' '.&mt('or deg. difficulty').' &ge; '.$threshold{'degdiff'}.'<br /> '.&mt('and total number of students with submissions').' &ge; '.$threshold{'numstudents'};
+
+    my @actionorder = ('handgrading','haserrors','abovethreshold','versionchanges','coursediscussion','coursenormalmail','coursecritmail');
+
+    foreach my $key (keys(%checkallowed)) {
+        $show{$key} = 0;
+        if ($checkallowed{$key}) {
+            unless ($display_settings{$key} eq 'off') {
+                $show{$key} = 1;
+            }
+        }
+    }
+
+    foreach my $item (@actionorder) {
+        unless ($item eq 'coursenormalmail' || $item eq 'coursecritmail') {
+            if ($show{$item}) {
+                $needitems = 1;
+                last;
+            }
+        }
+    }
+
+
     if (tie(my %bighash,'GDBM_File',$env{'request.course.fn'}.'.db',
 	    &GDBM_READER(),0640)) {
 	my $furl=$bighash{'first_url'};
@@ -210,234 +274,40 @@
     }
     $r->rflush();
 
-    &get_curr_thresholds(\%threshold,$cdom,$crs);
-    &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\@newdiscussions,\@tograde,\@bombs,\@warnings,$rowColor1,$rowColor2,\%threshold,$cdom,$crs,%res_title);
-    my ($msgcount,$critmsgcount) = &getmail(\@newmsgs,\@critmsgs);
-
-    $r->print('<br /><table border="0" width="100%" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%">');
-
-## UNGRADED ITEMS ##
-    $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>Problems requiring handgrading</b></td></tr>
-                  <tr>
-                   <td bgcolor="#ffffff">
-                     <table cellpadding="2" cellspacing="0" border="0" width="100%">
-END
-
-    if (@tograde > 0) {
-        $r->print('<tr bgcolor="#cccccc"><td><b><small>Problem Name</small></b></td><td align="right"><b><small>Number ungraded</small></b></td></tr>');
-        my $rowNum = 0;
-        foreach my $res (@tograde) {
-            if ($rowNum %2 == 1) {
-                $rowColor = $rowColor1;
-            } else {
-                $rowColor = $rowColor2;
-            }
-            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>');
-            $rowNum ++;
-        }
-    } 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 ($needitems) {
+        &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\%changed,\@newdiscussions,\@tograde,\@bombs,\@warnings,$rowColor1,$rowColor2,\%threshold,$cdom,$crs,\%res_title,\%show,$starttime);
     }
-    $r->print('</table></td></tr></table></td></tr></table><br />');
-
-## BOMBS ##
-     $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>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>');
+    if ($show{'coursenormalmail'}) {
+        &getnormalmail(\@newmsgs);
     }
-    $r->print('</table></td></tr></table></td></tr></table><br />');
-
-# DEGDIFF AND AV. TRIES TRIGGERS
-    $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>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>
-               <tr>
-                <td bgcolor="$tabbg" align="right"><a href="/adm/whatsnew?command=chgthreshold"><b><small>Change thresholds?</small></b></a></td>
-               </tr>
-                <tr>
-                <td bgcolor="#ffffff">
-                 <table width="100%" cellspacing="2" cellpadding="2" border="0">
-END
-    my $warningnum = 0;
-    if (@warnings > 0) {
-        @warnings = sort { &cmp_title($a,$b,\%res_title) } @warnings;
-        $r->print('<form name="reset_tracking" method="post">'.
-                 '  <input type="hidden" name="action" value="reset" />'."\n");
-        $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>');
-        foreach my $res (@warnings) {
-            if ($warningnum %2 == 1) {
-                $rowColor = $rowColor1;
-            } else {
-                $rowColor = $rowColor2;
-            }
-            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='.&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>');
+    if ($show{'coursecritmail'}) {
+        &getcritmail(\@critmsgs);
     }
-    $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%">');
+    $r->print(qq|<a href="javascript:changeAll('hide');">Hide All</a>&nbsp;&nbsp;<a href="javascript:changeAll('show');">Show All</a>|);
 
-## 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 ##
-    $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>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/communicate">'.$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 />');
-
-    $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>New critical messages in course</b></td>
-               </tr>
-               <tr>                 <td bgcolor="#ffffff">
-                 <table width="100%" cellspacing="0" cellpadding="0" border="0">
-END
+    $r->print('<br /><table border="0" width="100%" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%">');
 
-    if ($critmsgcount > 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 $rowNum = 0;
-        my $mailcount = 1;
-        foreach my $msg (@critmsgs) {
-            if ($rowNum %2 == 1) {
-                $rowColor = $rowColor1;
-            } else {
-                $rowColor = $rowColor2;
+    my $displayed = 0;
+    my $totalboxes = keys(%checkallowed);
+    my $halfway = int($totalboxes/2) + $totalboxes%2;
+    foreach my $actionitem (@actionorder) {
+        if ($checkallowed{$actionitem}) {
+            if ($displayed == $halfway) {
+                $r->print('</td><td width="5%">&nbsp;</td><td align="left" valign="top" width-"50%">');
             }
-            $r->print('<tr bgcolor="'.$rowColor.'"><td valign="top"><small>'.$mailcount.'. &nbsp;<small></td><td valign="top"><small><a href="/adm/email?folder=critical">'.$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 ++;
+            &display_launcher($r,$actionitem,\%checkallowed,$tabbg,$rowColor1,$rowColor2,\%show,\%headings,\%res_title,\@tograde,\%ungraded,\@bombs,\%bombed,\%changed,\@warnings,\%triggered,\@newdiscussions,\%unread,$msgcount,\@newmsgs,$critmsgcount,\@critmsgs,$interval);
+            $displayed ++; 
         }
-    } 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('
            </table>
           </td>
          </tr>
-        </table>');
-    $r->print('</td></tr></table>');
+        </table>
+      </td>
+    </tr>
+   </table>');
 }
 
 #-------------------------------
@@ -505,189 +375,265 @@
                </form>');
 }
 
+sub display_launcher {
+    my ($r,$action,$checkallowed,$tabbg,$rowColor1,$rowColor2,$show,
+        $headings,$res_title,$tograde,$ungraded,$bombs,$bombed,$changed,
+        $warnings,$triggered,$newdiscussions,$unread,$msgcount,$newmsgs,
+                                       $critmsgcount,$critmsgs,$interval) = @_;
+
+    if ($$checkallowed{$action}) {
+        &start_box($r,$tabbg,$show,$headings,$action);
+        if ($$show{$action}) {
+            if ($action eq 'handgrading') {    # UNGRADED ITEMS
+                &display_handgrade($r,$tograde,$rowColor1,$rowColor2,
+                                                                    $ungraded);
+            } elsif ($action eq 'haserrors') { # BOMBS
+                &display_haserrors($r,$bombs,$rowColor1,$rowColor2,$bombed,
+                                                                   $res_title);
+            } elsif ($action eq 'versionchanges') { # VERSION CHANGES
+                &display_versionchanges($r,$changed,$res_title,$rowColor1,
+                                                         $rowColor2,$interval);
+
+            } elsif ($action eq 'abovethreshold') { # DEGDIFF/AV. TRIES TRIGGERS
+                &display_abovethreshold($r,$warnings,$triggered,$res_title,
+                                                        $rowColor1,$rowColor2);
+            } elsif ($action eq 'coursediscussion') { # UNREAD COURSE DISCUSSION
+                &display_coursediscussion($r,$newdiscussions,$unread,
+                                                                   $res_title);
+            } elsif ($action eq 'coursenormalmail') { # NORMAL MESSAGES
+                &display_coursenormalmail($r,$msgcount,$newmsgs,$rowColor1,
+                                                                   $rowColor2);
+            } elsif ($action eq 'coursecritmail') { # CRITICAL MESSAGES
+                &display_coursecritmail($r,$critmsgcount,$critmsgs,$rowColor1,
+                                                                   $rowColor2);
+            }
+        }
+        &end_box($r);
+    }
+    return;
+}
+
 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,$rowColor1,$rowColor2,$threshold,$cdom,$crs,
+                                             $res_title,$show,$starttime) = @_;
     my $navmap = Apache::lonnavmaps::navmap->new();
     # force retrieve Resource to seed the part id cache we'll need it later
     my @allres=$navmap->retrieveResources(undef,sub {if ($_[0]->is_problem) { $_[0]->parts();} return 1;});
-    my %discussiontime = &Apache::lonnet::dump('discussiontimes',$cdom,$crs);
-    my %lastread = &Apache::lonnet::dump('nohist_'.$env{'request.course.id'}.
-                '_discuss',$env{'user.domain'},$env{'user.name'},'lastread');
-    my %lastreadtime = ();
-    my @discussions = ();
-    my ($classlist,$keylist) = &Apache::loncoursedata::get_classlist();
+    my %lastreadtime;
+    my %resourcetracker;
 
-    my %resourcetracker =  &Apache::lonnet::dump('nohist_resourcetracker',
-               $cdom,$crs);
-    my $warningnum = 0;
-    foreach my $key (keys(%lastread)) {
-        my $newkey = $key;
-        $newkey =~ s/_lastread$//;
-        $lastreadtime{$newkey} = $lastread{$key};
+# Resource version changes
+    if ($$show{'versionchanges'}) {
+        &checkversions($cdom,$crs,$navmap,$changed,$starttime);
+    }
+
+    if ($$show{'coursediscussions'}) {   
+        my %lastread = &Apache::lonnet::dump('nohist_'.
+                        $env{'request.course.id'}.'_discuss',
+                        $env{'user.domain'},$env{'user.name'},'lastread');
+        foreach my $key (keys(%lastread)) {
+            my $newkey = $key;
+            $newkey =~ s/_lastread$//;
+            $lastreadtime{$newkey} = $lastread{$key};
+        }
     }
+ 
+    if ($$show{'abovethreshold'}) {
+        %resourcetracker =  &Apache::lonnet::dump('nohist_resourcetracker',
+                                                                   $cdom,$crs);
+    }
+
+    my $warningnum = 0;
     foreach my $resource (@allres) {
         my $result = '';
         my $applies = 0;
         my $symb = $resource->symb();
-#        %{$$bombed{$symb}} = ();
+        %{$$bombed{$symb}} = ();
         %{$$ungraded{$symb}} = ();
         %{$$triggered{$symb}} = ();
         $$triggered{$symb}{numparts} = 0;
         my $title = $resource->compTitle();
         $$res_title{$symb} = $title;
         my $ressymb = $resource->wrap_symb();
+
 # Check for unread discussion postings
-	if ($resource->hasDiscussion()) {
-            push(@discussions,$ressymb);
-            my $prevread = 0;
-            my $unreadcount = 0;
-            %{$$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); }
-	}
+        if ($$show{'coursediscussion'}) {
+            &check_discussions($cdom,$crs,$resource,$symb,$ressymb,$title,
+                                       $newdiscussions,$unread,\&lastreadtime);
+        }
 
 # Check for ungraded problems
         if ($resource->is_problem()) {
-            my $ctr = 0;
-            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 ($handgradeable) {
-		foreach my $student (keys(%$classlist)) {
-		    my ($uname,$udom) = split(/:/,$student);
-		    my %status=&Apache::grades::student_gradeStatus($url,$symb,$udom,$uname,$partlist);
-		    my $submitted = 0;
-		    my $ungraded = 0;
-		    foreach (keys(%status)) {
-			$submitted = 1 if ($status{$_} ne 'nothing');
-			$ungraded = 1 if ($status{$_} =~ /^ungraded/);
-			my ($foo,$partid,$foo1) = split(/\./,$_);
-			if ($status{'resource.'.$partid.'.submitted_by'} ne '') {
-			    $submitted = 0;
-			}
-		    }
-		    next if (!$submitted || !$ungraded);
-		    $ctr ++;
-		}
-		if ($ctr) {
-		    $$ungraded{$symb}{count} = $ctr;
-		    $$ungraded{$symb}{title} = $title;
-		    push(@{$tograde}, $symb);
-		}
-	    }
+            if ($$show{'handgrading'}) {
+                &check_handgraded($resource,$symb,$title,$cdom,$crs,$ungraded,
+                                                                     $tograde);
+            }
         }
 
 # Check for bombs
-        if ($resource->getErrors()) {
-            my $errors = $resource->getErrors();
-	    $errors =~ s/^,//;
-            my @bombs = split(/,/, $errors);
-            my $errorcount = scalar(@bombs);
-            my $errorlink = '<a href="/adm/email?display='.
-                            &Apache::lonnet::escape($bombs[0]).'">'.
-                            $title.'</a>';
-            $$bombed{$symb}{errorcount} = $errorcount;
-            $$bombed{$symb}{errorlink} = $errorlink;
-            push(@{$bombs}, $symb);
+        if ($$show{'haserrors'}) {
+            &check_bombed($resource,$symb,$title,$bombs,$bombed);
         }
-# Compile maxtries and degree of difficulty for problem parts, unless handgradeable
-        my @parts = @{$resource->parts()};
-        my %stats;
-        my %lastreset = ();
-        my $warning = 0;
-        my $rowColor;
-        foreach my $part (@parts) {
+
+# Maxtries and degree of difficulty for problem parts, unless handgradeable
+        if ($$show{'abovethreshold'}) {  
+            &check_thresholds($resource,$symb,\%resourcetracker,$triggered,
+                       $threshold,$warnings,$warningnum,$rowColor1,$rowColor2);
+        }
+
+    }
+}
+
+sub check_discussions {
+    my ($cdom,$crs,$resource,$symb,$ressymb,$title,$newdiscussions,$unread,
+                                                           $lastreadtime) = @_;  
+# Check for unread discussion postings
+    if ($resource->hasDiscussion()) {
+        my $prevread = 0;
+        my $unreadcount = 0;
+        %{$$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); }
+    }
+}
+
+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') {
-                next;
+                $handgradeable=1; last;
             }
-            %{$stats{$part}} = ();
-            my ($attempts,$users,$corrects,$degdiff,$av_attempts);
-            if (exists($resourcetracker{$symb."\0".$part."\0attempts"})) {
-                $attempts = $resourcetracker{$symb."\0".$part."\0attempts"};
-            }
-            if (exists($resourcetracker{$symb."\0".$part."\0users"})) {
-                $users = $resourcetracker{$symb."\0".$part."\0users"};
-            }
-            if (exists($resourcetracker{$symb."\0".$part."\0correct"})) {
-                $corrects = $resourcetracker{$symb."\0".$part."\0correct"};
-            }
-            if ($attempts > 0) {
-                $degdiff =  1 - ($corrects/$attempts);
-                $degdiff = sprintf("%.2f",$degdiff);
-            }
-            if ($users > 0) {
-                $av_attempts = $attempts/$users;
-                $av_attempts = sprintf("%.2f",$av_attempts);
-            }
-            if ((($degdiff ne '' && $degdiff >= $$threshold{'degdiff'}) || ($av_attempts ne '' && $av_attempts >= $$threshold{'av_attempts'})) && ($users >= $$threshold{'numstudents'})) {
-                $stats{$part}{degdiff} = $degdiff;
-                $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});
-                }
-                $warning = 1;
+        }
+        if ($handgradeable) {
+            my @ungraded = &Apache::bridgetask::get_users_in_queue(
+                                             'gradingqueue',$symb,$cdom,$cnum);
+            if (@ungraded > 0) {
+                $$ungraded{$symb}{count} = scalar(@ungraded);
+                $$ungraded{$symb}{title} = $title;
+                push(@{$tograde}, $symb);
             }
         }
-        if ($warning) {
-            if ($warningnum %2 == 1) {
-                $rowColor = $rowColor1;
-            } else {
-                $rowColor = $rowColor2;
+    }
+}
+
+sub check_bombed {
+    my ($resource,$symb,$title,$bombs,$bombed) = @_;
+    if ($resource->getErrors()) {
+        my $errors = $resource->getErrors();
+        $errors =~ s/^,//;
+        my @bombs = split(/,/, $errors);
+        my $errorcount = scalar(@bombs);
+        my $errorlink = '<a href="/adm/email?display='.
+                        &Apache::lonnet::escape($bombs[0]).'">'.
+                        $title.'</a>';
+        $$bombed{$symb}{errorcount} = $errorcount;
+        $$bombed{$symb}{errorlink} = $errorlink;
+        push(@{$bombs}, $symb);
+    }
+}
+
+sub check_thresholds {
+    my ($resource,$symb,$resourcetracker,$triggered,$threshold,$warnings,
+                                       $warningnum,$rowColor1,$rowColor2) = @_;
+# Compile maxtries and degree of difficulty for problem parts, unless handgradeable
+    my @parts = @{$resource->parts()};
+    my %stats;
+    my %lastreset = ();
+    my $warning = 0;
+    my $rowColor;
+    foreach my $part (@parts) {
+        if ($resource->handgrade($part) eq 'yes') {
+            next;
+        }
+        %{$stats{$part}} = ();
+        my ($attempts,$users,$corrects,$degdiff,$av_attempts);
+        if (exists($$resourcetracker{$symb."\0".$part."\0attempts"})) {
+            $attempts = $$resourcetracker{$symb."\0".$part."\0attempts"};
+        }
+        if (exists($$resourcetracker{$symb."\0".$part."\0users"})) {
+            $users = $$resourcetracker{$symb."\0".$part."\0users"};
+        }
+        if (exists($$resourcetracker{$symb."\0".$part."\0correct"})) {
+            $corrects = $$resourcetracker{$symb."\0".$part."\0correct"};
+        }
+        if ($attempts > 0) {
+            $degdiff =  1 - ($corrects/$attempts);
+            $degdiff = sprintf("%.2f",$degdiff);
+        }
+        if ($users > 0) {
+            $av_attempts = $attempts/$users;
+            $av_attempts = sprintf("%.2f",$av_attempts);
+        }
+        if ((($degdiff ne '' && $degdiff >= $$threshold{'degdiff'}) || ($av_attempts ne '' && $av_attempts >= $$threshold{'av_attempts'})) && ($users >= $$threshold{'numstudents'})) {
+            $stats{$part}{degdiff} = $degdiff;
+            $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;
-            foreach my $part (@parts) {
-                if (exists($stats{$part}{users})) {
-                    my $resetname = 'reset_'.&Apache::lonnet::escape($symb."\0".$part);
-                    my $resettitle = 'title_'.&Apache::lonnet::escape($symb."\0".$part);
-                    if ($$triggered{$symb}{numparts}) {
-                        $$triggered{$symb}{text} .= '<tr bgcolor="'.$rowColor.'">'."\n";
-                    }
-                    if (@parts > 1) {
-                        $$triggered{$symb}{text} .= '
-                         <td align="right"><small>part - '.$part.'<small></td>';
-                    } else {
-                        $$triggered{$symb}{text} .= '
-                         <td align="right"><small>single part</small></td>';
-                    }
+            $warning = 1;
+        }
+    }
+    if ($warning) {
+        if ($$warningnum %2 == 1) {
+            $rowColor = $rowColor1;
+        } else {
+            $rowColor = $rowColor2;
+        }
+        $$triggered{$symb}{title} = $resource->title;
+        foreach my $part (@parts) {
+            if (exists($stats{$part}{users})) {
+                my $resetname = 'reset_'.&Apache::lonnet::escape($symb."\0".$part);
+                my $resettitle = 'title_'.&Apache::lonnet::escape($symb."\0".$part);
+                if ($$triggered{$symb}{numparts}) {
+                    $$triggered{$symb}{text} .= '<tr bgcolor="'.$rowColor.'">'."\n";
+                }
+                if (@parts > 1) {
                     $$triggered{$symb}{text} .= '
-                         <td align="right"><small>'.$stats{$part}{users}.'</small></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} ++;
+                     <td align="right"><small>part - '.$part.'<small></td>';
+                } else {
+                    $$triggered{$symb}{text} .= '
+                     <td align="right"><small>single part</small></td>';
                 }
+                $$triggered{$symb}{text} .= '
+                     <td align="right"><small>'.$stats{$part}{users}.'</small></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} ++;
             }
-            push(@{$warnings},$symb);
-            $warningnum ++;
         }
+        push(@{$warnings},$symb);
+        $$warningnum ++;
     }
 }
 
+
 sub get_curr_thresholds {
     my ($threshold,$cdom,$crs) = @_;
     my %coursesettings = &Apache::lonnet::dump('environment',
@@ -768,8 +714,8 @@
     return $setoutput;
 }
 
-sub getmail {
-    my ($newmsgs,$critmsgs) = @_;
+sub getnormalmail {
+    my ($newmsgs) = @_;
 # Check for unread mail in course
     my $msgcount = 0;
 
@@ -799,7 +745,11 @@
             }
         }
     }
+    return $msgcount;
+}
 
+sub getcritmail {
+    my ($critmsgs) = @_; 
 # Check for critical messages in course
     my %what=&Apache::lonnet::dump('critical');
     my $result = '';
@@ -826,7 +776,269 @@
             }
         }
     }
-    return ($msgcount,$critmsgcount);
+    return $critmsgcount;
+}
+
+
+sub checkversions {
+    my ($cdom,$crs,$navmap,$changed,$starttime) = @_;
+    my %changes=&Apache::lonnet::dump('versionupdate',$cdom,$crs);
+    my ($tmp) = keys(%changes);
+    if ($tmp =~/^error\:/) {
+        &Apache::lonnet::logthis('Error retrieving version update information: '.
+        $tmp.' for '.$cdom.'_'.$crs.' in whatsnew');
+    } else {
+        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');
+                    print STDERR "revdate for $root and $extension is $revdate\n";
+                    $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) {
+                        my $symb = $res->symb();
+                        %{$$changed{$symb}} = (
+                                                current => $currentversion,
+                                                version => $version,
+                                                revdate => $revdate,
+                        );
+                    }
+                }
+            }
+        }
+    }
+    return;
+}
+
+sub display_handgrade {
+    my ($r,$tograde,$rowColor1,$rowColor2,$ungraded) = @_;
+    my $rowColor;
+    my %lt = &Apache::lonlocal::texthash(
+                        'prna' => 'Problem Name',
+                        'nmun' => 'Number ungraded',
+                        'nopr' => 'No problems require handgrading',
+    );
+    if (@{$tograde} > 0) {
+        $r->print('<tr bgcolor="#cccccc"><td><b><small>'.$lt{'prna'}.'</small></b></td><td align="right"><b><small>'.$lt{'nmun'}.'</small></b></td></tr>');
+        my $rowNum = 0;
+        foreach my $res (@{$tograde}) {
+            if ($rowNum %2 == 1) {
+                $rowColor = $rowColor1;
+            } else {
+                $rowColor = $rowColor2;
+            }
+            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>');
+            $rowNum ++;
+        }
+    } else {
+        $r->print('<tr><td bgcolor="#ffffff"><br><center><i><b><small>&nbsp;&nbsp;'.$lt{'nopr'}.'&nbsp;&nbsp;</small><br><br></b></i></td></tr>');
+    }
+}
+
+sub display_haserrors {
+    my ($r,$bombs,$rowColor1,$rowColor2,$bombed,$res_title) = @_;
+    my $bombnum = 0;
+    my $rowColor;
+    my %lt = &Apache::lonlocal::texthash(
+                                   reso => 'Resource',
+                                   nmer => 'Number of errors',
+                                   noer => 'No problems with errors',
+    );
+    if (@{$bombs} > 0) {
+        $r->print('<tr bgcolor="#cccccc"><td><b><small>'.$lt{'reso'}.'</small></b></td><td align="right"><b><small>'.$lt{'nmer'}.'</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>'.$lt{'noer'}.'</small></i></b></center><br /></td></tr>');
+    }
+    return;
+}
+
+sub display_abovethreshold {
+    my ($r,$warnings,$triggered,$res_title,$rowColor1,$rowColor2) = @_;
+    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',
+    );
+    my $rowColor; 
+    my $warningnum = 0;
+    if (@{$warnings} > 0) {
+        @{$warnings} = sort { &cmp_title($a,$b,$res_title) } @{$warnings};
+        $r->print('<form name="reset_tracking" method="post">'.
+                '  <input type="hidden" name="action" value="reset" />'."\n");
+        $r->print('<tr bgcolor="#cccccc"><td><b><small>'.$lt{'reso'}.'</small></b></td><td align="right"><b><small>'.$lt{'part'}.'</small></b></td><td align="right"><b><small>'.$lt{'nust'}.'</small></b></td><td align="right"><b><small>'.$lt{'avat'}.'</small></b></td><td align="right"><b><small>'.$lt{'dedi'}.'</small></b></td><td align="right"><b><small>'.$lt{'lare'}.'</small></b></td><td align="right"><b><small>'.$lt{'reco'}.'</small></b></td></tr>');
+        foreach my $res (@{$warnings}) {
+            if ($warningnum %2 == 1) {
+                $rowColor = $rowColor1;
+            } else {
+                $rowColor = $rowColor2;
+            }
+            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='.&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="'.$lt{'rese'}.'/></form>');
+    } else {
+        $r->print('<tr><td bgcolor="#ffffff"><br /><center><b><i><small>'.$lt{'nopr'}.'</small></i></b></center><br /></td></tr>');
+    }
+}
+
+sub display_versionchanges {
+    my ($r,$changed,$res_title,$rowColor1,$rowColor2,$interval) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+        'reso' => 'Resource',
+        'revd' => 'Last revised',
+        'newv' => 'New version',
+        'veru' => 'Version used',
+        'noup' => 'No updated versions', 
+    );
+    my $rowColor;
+    if (keys(%{$changed}) > 0) {
+        $r->print('<tr bgcolor="#cccccc"><td><b><small>'.$lt{'reso'}.'</small></b></td><td><b><small>'.$lt{'revd'}.'</small></b></td><td><b><small>'.$lt{'newv'}.'</small></b></td><td><b><small>'.$lt{'veru'}.'</small></b></td></tr>');
+        
+        
+        my @changes = sort { &cmp_title($a,$b,$res_title) } keys(%{$changed});
+        my $changenum = 0;
+        foreach my $item (@changes) {
+            if ($changenum %2 == 1) {
+                $rowColor = $rowColor1;
+            } else {
+                $rowColor = $rowColor2;
+            }
+            my ($map,$id,$url)=&Apache::lonnet::decode_symb($item);
+            my $linkurl=&Apache::lonnet::clutter($url);
+            $linkurl .= '?symb='.&Apache::lonnet::escape($item);
+
+            $r->print('<tr bgcolor="'.$rowColor.'"><td><small><a href="'.$linkurl.'">'.$$res_title{$item}.'</a></small></td><td><small>'.$$changed{$item}{'revdate'}.'</small></td><td><small>'.$$changed{$item}{'current'}.'</small></td><td><small>'.$$changed{$item}{'version'}.'</small></td></tr>');
+            $changenum ++;
+        }
+    } else {
+        $r->print('<tr><td bgcolor="#ffffff"><br /><center><b><i><small>'.$lt{'noup'}.' '.$interval.'</small></i></b></center><br /></td></tr>');
+    }
+    return;
+}
+ 
+sub display_coursediscussion {
+    my ($r,$newdiscussions,$unread,$res_title,$rowColor1,$rowColor2) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+                'loca' => 'Location',
+                'type' => 'Type',
+                'numn' => 'Number of new posts',
+                'noun' => 'No unread posts in course discussions',
+    );
+    my $rowColor;
+    if (@{$newdiscussions} > 0) {
+        $r->print('<tr bgcolor="#cccccc"><td><b><small>'.$lt{'loca'}.
+                  '</small></b></td><td><b><small>'.$lt{'type'}.
+                  '</small></b><td align="right"><b><small>'.$lt{'numn'}.
+                  '</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>'.
+                  $lt{'noun'}.'</small></b></i><br><br></td></tr>');
+    }
+}
+
+sub display_coursenormalmail {
+    my ($r,$msgcount,$newmsgs,$rowColor1,$rowColor2) = @_;
+    my $rowColor;
+    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/communicate">'.$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>'.&mt('No new course messages').'</small></i></b><br /><br /></center></td></tr>');
+    }
+}
+
+sub display_coursecritmail {
+    my ($r,$critmsgcount,$critmsgs,$rowColor1,$rowColor2) = @_;
+    my $rowColor;
+    if ($critmsgcount > 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 (@{$critmsgs}) {
+            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/email?folder=critical">'.$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>'.&mt('No unread critical messages in course').'</small></i></b><br /><br /></center></td></tr>');
+    }
 }
 
 sub cmp_title {
@@ -837,4 +1049,83 @@
     return $atitle cmp $btitle;
 }
 
+sub get_display_settings {
+    my $udom = $env{'user.domain'};
+    my $uname = $env{'user.name'};
+    my $cid = $env{'request.course.id'};
+    my %settings = &Apache::lonnet::dump('nohist_whatsnew',$udom,$uname,$cid); 
+    my ($tmp) = keys(%settings);
+    if ($tmp=~/^error:/) {
+        %settings = ();
+        unless ($tmp eq 'error: 2 tie(GDBM) Failed while attempting dump') {
+            &logthis('Error retrieving whatsnew settings: '.$tmp.' for '.
+                                $uname.':'.$udom.' for course: '.$cid);
+        }
+    }
+    return %settings;
+}
+
+sub start_box {
+    my ($r,$tabbg,$show,$heading,$caller) = @_;
+    my %lt = &Apache::lonlocal::texthash( 
+                       chth => 'Change thresholds?',
+                       chin => 'Change interval?',
+    );
+    my $showhide;
+    if ($$show{$caller}) {
+        $showhide = '<b><a href="javascript:change_display('."'".$caller.
+                                           "','hide'".');">Hide</a></b>';
+   
+    } else {
+        $showhide = '<b><a href="javascript:change_display('."'".$caller.
+                                            "','show'".');">Show</a></b>';
+    }
+    
+    $r->print('
+         <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.'">
+                <table width="100%" border="0" cellspacing="0" cellpadding="0">
+                 <tr>
+                  <td><b>'.$$heading{$caller}.'</b></td>
+                  <td valign="top" align="right">'.$showhide.'</td>
+                 </tr>
+                </table>
+               </td>
+              </tr>');
+     if (($caller eq 'abovethreshold') && ($$show{$caller})) {
+         $r->print('
+              <tr>
+                <td bgcolor="'.$tabbg.'" align="right"><a href="/adm/whatsnew?command=chgthreshold"><b><small>'.$lt{'chth'}.'</small></b></a></td>
+              </tr>');
+     } elsif (($caller eq 'versionchanges') && ($$show{$caller})) {
+         $r->print('
+              <tr>
+                <td bgcolor="'.$tabbg.'" align="right"><a href="/adm/whatsnew?command=chginterval"><b><small>'.$lt{'chin'}.'</small></b></a></td>
+              </tr>');
+     }
+     $r->print('
+              <tr>
+               <td bgcolor="#ffffff">
+                <table cellpadding="2" cellspacing="0" border="0" width="100%">
+');
+    return;
+}
+
+sub end_box {
+    my ($r) = shift;
+    $r->print('
+      </table>
+     </td>
+    </tr>
+   </table>
+  </td>
+ </tr>
+</table><br />');
+    return;
+}
+
 1;

--raeburn1133565467--