File:  [LON-CAPA] / loncom / interface / lonwhatsnew.pm
Revision 1.39: download - view: text, annotated - select for diffs
Mon Dec 19 21:39:37 2005 UTC (18 years, 4 months ago) by raeburn
Branches: MAIN
CVS tags: HEAD
Display of whatsnew page on entering a course can be set for specific courses (override user prefs).  Can suppress count of unread posts per resource. Link to first resource at top of page not shown if NEW button used to get to whatsnew. What's new no longer restricted to CC role - accessible to adavnced roles in a course.

#
# $Id: lonwhatsnew.pm,v 1.39 2005/12/19 21:39:37 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#


package Apache::lonwhatsnew;

use strict;
use lib qw(/home/httpd/lib/perl);
use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon();
use Apache::lonlocal;
use Apache::loncoursedata();
use Apache::lonnavmaps();
use Apache::lonuserstate;
use Apache::Constants qw(:common :http);
use Time::Local;
use GDBM_File;

#----------------------------
# handler
#
#----------------------------

sub handler {
    my $r = shift;
    if ($r->header_only) {
        &Apache::loncommon::content_type($r,'text/html');
        $r->send_http_header;
        return OK;
    }
    &Apache::loncommon::get_unprocessed_cgi(
                                   $ENV{'QUERY_STRING'},['command','refpage']);

    my $command = $env{'form.command'};
    my $refpage = $env{'form.refpage'};

    &Apache::loncommon::content_type($r,'text/html');
    $r->send_http_header;
    my $crsid = $env{'request.course.id'};
    $crsid =~ s/_/\//; 
    if ((!($env{'request.course.id'})) || 
                             ($env{'request.role'} !~ /\Q$crsid\E$/)) {
        # Not in a course, or no role in course
        $env{'user.error.msg'}="/adm/whatsnew::0:0:Cannot display what's new screen";
        return HTTP_NOT_ACCEPTABLE;
    }

    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,
    );

    $r->print(&display_header($command,\%checkallowed));

    &Apache::lonhtmlcommon::clear_breadcrumbs();
    &Apache::lonhtmlcommon::add_breadcrumb
            ({href=>'/adm/whatsnew',
              text=>"Display Action Items"});
    if (($command eq 'chgthreshold') && (&Apache::lonnet::allowed('vgr',$env{'request.course.id'}))) {
        &Apache::lonhtmlcommon::add_breadcrumb
            ({href=>'/adm/whatsnew?command=chgthreshold&refpage='.$refpage,
              text=>"Change thresholds"});
        $r->print(&Apache::lonhtmlcommon::breadcrumbs
            (undef,'Course Action Items','Course_Action_Items_Thresholds'));
    } elsif (($command eq 'chginterval') && (&Apache::lonnet::allowed('vgr',$env{'request.course.id'}))) {
        &Apache::lonhtmlcommon::add_breadcrumb
            ({href=>'/adm/whatsnew?command=chginterval&refpage='.$refpage,
              text=>"Change interval"});
        $r->print(&Apache::lonhtmlcommon::breadcrumbs
            (undef,'Course Action Items','Course_Action_Items_Intervals'));
    } elsif (($command eq 'chgdisc') && (&Apache::lonnet::allowed('pch',$env{'request.course.id'}))) {
        &Apache::lonhtmlcommon::add_breadcrumb
            ({href=>'/adm/whatsnew?command=chgdisc&refpage='.$refpage,
              text=>"Change discussion display"});
        $r->print(&Apache::lonhtmlcommon::breadcrumbs
            (undef,'Course Action Items','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
            (undef,'Course Action Items','Course_Action_Items_Initialization'));
    } else {
        $r->print(&Apache::lonhtmlcommon::breadcrumbs
            (undef,'Course Action Items','Course_Action_Items_Display'));
    }
    &display_main_box($r,$command,$refpage,\%checkallowed);
    return OK;
}

#------------------------------
# display_main_box
#
# Display all the elements within the main box
#------------------------------
                                                                                
sub display_main_box {
    my ($r,$command,$refpage,$checkallowed) = @_;
    my $domain=&Apache::loncommon::determinedomain();
    my $tabbg=&Apache::loncommon::designparm('coordinator.tabbg',$domain);
    $r->print('<table width="100%" border="0" cellpadding="5" cellspacing="0"><tr><td width="100%">');

    my %threshold_titles = &Apache::lonlocal::texthash (
                         av_attempts => 'Average number of attempts',
                         degdiff => 'Degree of difficulty',
                         numstudents => 'Total number of students with submissions',
    );

    my %interval_titles = &Apache::lonlocal::texthash (
                            -1 => 'since start of course',
                       2592000 => 'since last month',
                        604800 => 'since last week',
                         86400 => 'since yesterday',
    );

    my %initpage = &Apache::lonlocal::texthash (
                     firstres => 'first resource in the course',
                     whatsnew => "what's new? page",
                     userpref => 'your general user preferences',
                     coursespecific => 'specific setting for this course',
                   );
    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
    my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};

    if (($command eq 'chgthreshold') && 
               (&Apache::lonnet::allowed('vgr',$env{'request.course.id'}))) {
        &display_threshold_config($r,$refpage,$tabbg,\%threshold_titles,
                                                                   $cdom,$crs);
    } elsif (($command eq 'chginterval') && 
               (&Apache::lonnet::allowed('opa',$env{'request.course.id'}))) {
        &display_interval_config($r,$refpage,\%interval_titles);
    } elsif (($command eq 'chgdisc') && 
               (&Apache::lonnet::allowed('pch',$env{'request.course.id'}))) {
        &display_discussion_config($r,$refpage);
    } elsif ($command eq 'courseinit') {
        &courseinit_config($r,$refpage,\%initpage);
    } else {
        &display_actions_box($r,$command,$refpage,\%threshold_titles,
                        \%interval_titles,\%initpage,$cdom,$crs,$checkallowed);
    }
    $r->print(<<END_OF_BLOCK);
  </td>
 </tr>
</table><br />
</body>
</html>
END_OF_BLOCK
}

#-------------------------------
# display_header
#
# Display the header information and set
# up the HTML
#-------------------------------

sub display_header {
    my ($command,$checkallowed) = @_;
    my $html=&Apache::lonxml::xmlbegin();
    my $bodytag=&Apache::loncommon::bodytag('Course Action Items');
    my $scripttag;
    unless ($command eq 'chgthreshold' || $command eq 'chginterval') {
       $scripttag = <<"END";
<script type="text/javascript">
function change_display(caller,change) {
    caller.value = change;
    document.visible.submit(); 
}

function changeAll(change) {
END
        foreach my $item (keys(%{$checkallowed})) {
            if ($$checkallowed{$item}) {
                $scripttag.='document.visible.display_'.$item.'.value=change'.
                            "\n";
            }
        }
        $scripttag.='document.visible.submit();
}
</script>
';
    }
    return(<<ENDHEAD);
$html
<head>
<title>Course Action Items</title>
$scripttag
</head>
$bodytag
ENDHEAD
}

#-------------------------------
# display_actions_box
#
# Display the action items
#
#-------------------------------
                                                                                
sub display_actions_box {
    my ($r,$command,$refpage,$threshold_titles,$interval_titles,$initpage,
                                                $cdom,$crs,$checkallowed) = @_;
    my $rowColor1 = "#ffffff";
    my $rowColor2 = "#eeeeee";

    my $udom = $env{'user.domain'};
    my $uname = $env{'user.name'};
    my $cid = $env{'request.course.id'};

    my %lt = &Apache::lonlocal::texthash(
                 'yacc' => 'You are accessing an invalid course.',
                 'gtfr' => 'Go to first resource',
                 'pgse' => 'Page set to be displayed after you have selected a role in this course?',
                 'hial' => 'Hide all',
                 'shal' => 'Show all',
    );

    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;
    if ($env{'request.role'}=~/^(cc|in|ta|ep)/) {
        $function='coordinator';
    }
    if ($env{'request.role'}=~/^(su|dc|ad|li)/) {
        $function='admin';
    }

    my $result;
    if ($command eq 'newcourseinit') {
        $result = &store_courseinit_setting($uname,$udom,$cid,$initpage);
    }

    my %threshold = (
                      av_attempts => 2,
                      degdiff => 0.5,
                      numstudents => 2,
                     );
    my %pagedesc = &Apache::lonlocal::texthash (
                     firstres => 'First resource',
                     whatsnew => "What's New page",
                     userpref => 'user preference',
                     coursespecific => 'course only',
                     default => 'default',
                   );

    my ($initcontrol,$initdisp) = &curr_courseinit();
    my $currinit = $pagedesc{$initdisp}.' ('.$pagedesc{$initcontrol}.')';

    my $pgbg=&Apache::loncommon::designparm($function.'.pgbg',$domain);
    my $tabbg=&Apache::loncommon::designparm($function.'.tabbg',$domain);

    unless ($cid) {
        $r->print('<br /><b><center>'.$lt{'yacc'}.'</center></b><br /><br />');
        return;
    }

    if ($refpage eq 'start') {
        if (tie(my %bighash,'GDBM_File',$env{'request.course.fn'}.'.db',
            &GDBM_READER(),0640)) {
            my $furl=$bighash{'first_url'};
            untie(%bighash);
            $r->print('<font size="+1"><a href="'.$furl.'">'.$lt{'gtfr'}.
                  '</a></font><br />');
        }
    }
    $r->print($lt{'pgse'}.' '.&mt('Currently: [_1]','<i>'.$currinit.'</i>').
              '<nobr>&nbsp;&nbsp;'.&mt('[_1] for just [_2]','<b>Change</b>',
              '<a href="/adm/whatsnew?command=courseinit&refpage='.$refpage.
              '">this course</a>').' '.&mt('or for all [_1].',
              '<a href="/adm/preferences?action=changecourseinit&refpage='.
              $refpage.'">your courses</a>').'</nobr><br /><hr />');
                                                                                        
    if ($command eq 'reset') {
        $result = &process_reset($cdom,$crs);
    } elsif ($command eq 'update') {
        $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 storing whatsnew settings: '.
            $store_result.' for '.'user '.$uname.':'.$udom.' in course '.$cid);
        $result .= &mt('Unable to store visibility settings due to [_1]',
                       $store_result); 
    }

    if ($result) {
        $r->print($result.'<hr width="100%" />');
    }
    $r->rflush();


    my %display_settings = &get_display_settings($uname,$udom,$cid);
    my $timediff = $display_settings{$cid.':interval'};
    unless (defined($timediff)) { $timediff = 604800; } 
    my $now = time;
    my $interval = $$interval_titles{$timediff};
    if ($timediff == -1) {
        $timediff = time;
    } 
    my $starttime = $now - $timediff;
    my $countunread = $display_settings{$cid.':countunread'};
    unless (defined($countunread)) {
        $countunread = 'on';
    }

    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 messages',
                coursecritmail => 'New critical messages in course',
    );

    if ($$checkallowed{'abovethreshold'}) {
        &get_curr_thresholds(\%threshold,$uname,$udom,$cid,$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{$cid.':'.$key} eq 'hide') {
                $show{$key} = 1;
            }
        }
    }

    foreach my $item (@actionorder) {
        unless ($item eq 'coursenormalmail' || $item eq 'coursecritmail') {
            if ($show{$item}) {
                $needitems = 1;
                last;
            }
        }
    }

    if ($needitems) {
        &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\%changed,\@newdiscussions,\@tograde,\@bombs,\@warnings,$rowColor1,$rowColor2,\%threshold,$cdom,$crs,\%res_title,\%show,$starttime,$countunread);
    }
    if ($show{'coursenormalmail'}) {
        &getnormalmail(\@newmsgs);
    }
    if ($show{'coursecritmail'}) {
        &getcritmail(\@critmsgs);
    }

    $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 ($$checkallowed{$item}) {
            $r->print('<input type="hidden" name="display_'.$item.'" />'."\n");
        }
    }

    $r->print('<input type="hidden" name="refpage" value="'.$refpage.'"></form><br /><table border="0" width="100%" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%">');

    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%">');
            }
            &display_launcher($r,$actionitem,$refpage,$checkallowed,$tabbg,$rowColor1,$rowColor2,\%show,\%headings,\%res_title,\@tograde,\%ungraded,\@bombs,\%bombed,\%changed,\@warnings,\%triggered,\@newdiscussions,\%unread,$msgcount,\@newmsgs,$critmsgcount,\@critmsgs,$interval,$countunread);
            $displayed ++; 
        }
    }
    $r->print('
           </table>
          </td>
         </tr>
        </table>
      </td>
    </tr>
   </table>');
}

#-------------------------------
# display_threshold_config
#
# Display the threshold setting screen 
#
#-------------------------------
                                                                                
sub display_threshold_config {
    my ($r,$refpage,$tabbg,$threshold_titles,$cdom,$crs) = @_;
    my $uname = $env{'user.name'};
    my $udom = $env{'user.dom'};
    my $cid = $env{'request.course.id'};
    my %threshold = ();
    my $rowColor1 = "#ffffff";
    my $rowColor2 = "#eeeeee";
    my $rowColor;

    my @thresholditems = ("av_attempts","degdiff","numstudents");
    foreach my $item (@thresholditems) {
        $threshold{$item} = '';
    }
    my %threshold_titles = &Apache::lonlocal::texthash(
                         av_attempts => 'Average number of attempts',
                         degdiff => 'Degree of difficulty',
                         numstudents => 'Total number of students with submissions',
                         );
    &get_curr_thresholds(\%threshold,$uname,$udom,$cid,$cdom,$crs);

    $r->print('<br /><form name="thresholdform" method="post" action="/adm/whatsnew">
        <table border="0" cellpadding="2" cellspacing="4">
         <tr>
          <td align="left" valign="top" width="45%">
           <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000">
            <tr>
             <td>
               <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000">
                <tr>
                <td bgcolor="#ffffff">
                 <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) {
        my $parameter = $env{'request.course.id'}.':threshold_'.$type;
# onchange is javascript to automatically check the 'Set' button.
        my $onchange = 'onFocus="javascript:window.document.forms'.
              "['thresholdform'].elements['".$parameter."_setparmval']".
              '.checked=true;"';
        if ($rowNum %2 == 1) {
            $rowColor = $rowColor1;
        } else {
            $rowColor = $rowColor2;
        }
        $r->print('
     <tr bgcolor="'.$rowColor.'">
      <td>'.$threshold_titles{$type}.'</td>
      <td>'.&Apache::lonhtmlcommon::textbox($parameter.'_value',
                                            $threshold{$type},
                                            10,$onchange).'</td>
      <td>'
           .&Apache::lonhtmlcommon::checkbox($parameter.'_setparmval').
      '</td>
     </tr>');
        $rowNum ++;
    }
    $r->print('</table></td></tr></table></td></tr></table>
           <br /><input type="submit" name="threshold" value="Make changes" />
                 <input type="hidden" name="command" 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) = @_;
    my $current = &get_current($env{'user.name'},$env{'user.domain'},
                                $env{'request.course.id'},'interval');
    $r->print('<br />'.&mt('Choose the time window to use for display of version changes for resources in the course.'));
    unless ($current eq '') {
        $r->print(' '.&mt('Current value is [_1]','<b>'.
                  $$interval_titles{$current}.'</b>.'));
    }
    $r->print('<br /><br />
<form method="post" name="intervalswitch" action="/adm/whatsnew">
<input type="hidden" name="command" value="newinterval" />
<input type="hidden" name="refpage" value="'.$refpage.'" />
<select name="interval">
');
    foreach my $key (reverse sort ({$a cmp $b} (keys(%{$interval_titles})))) {
        $r->print('<option value="'.$key.'">Version changes '.$$interval_titles{$key}.
                  '</option>'."\n");
    }
    $r->print('</select>&nbsp;&nbsp;
               <input type="submit" name="display" value="'.
               &mt('Change interval').'" /></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 %status = (
                    on => 'checked="checked"',
                    off => 'checked="checked"',
                 );
    $status{$current} = '';
    $r->print('<br />'.&mt('Choose whether or not to display a count of the number of new posts for each resource or bulletin board which has unread posts.').'<br />'.&mt('This can increase the time taken to gather data for the [_1] page by a few seconds.',"<i>What's New?</i>").'&nbsp;&nbsp;'.&mt('Currently set to [_1] .'),"<b>$current</b>.");
    $r->print('<br /><br />
<form method="post" name="discussionswitch" action="/adm/whatsnew">'.
&mt('Display of unread post counts?').'&nbsp;
<input type="hidden" name="command" value="newdiscconf" />
<input type="hidden" name="refpage" value="'.$refpage.'" />
<input type ="radio" '.$status{'on'}.' name="countunread" value="on">on
&nbsp;&nbsp;&nbsp;
<input type ="radio" '.$status{'off'}.' name="countunread" value="off">off
');
    $r->print('<br/><br />
               <input type="submit" name="display" value="'.
               &mt('Make changes').'" /></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 %lt = &Apache::lonlocal::texthash(
                             'chwp' => 'Choose which page will be displayed when you enter this course after selecting a role.',
                             'cuva' => 'Current value is determined by',
                             'anis' => 'and is set to display',
                             'padc' => 'Page display controlled by',
                             'chce' => 'Choose course entry',
                             'moce' => 'Modify course entry',
    );
    $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) {
        $r->print('<nobr><input type="radio" name="courseinit_control" value="'.
                   $choice.'"/>'.$$initpage{$choice}.'&nbsp;&nbsp;</nobr>');
    }
    $r->print('<br /><br />'.&mt('If').' '.$$initpage{'coursespecific'}.
              '<br />'.$lt{'chce'}." \n");
    foreach my $choice (@chgentry) {
        $r->print('<nobr><input type="radio" name="courseinit_page" value="'.
                  $choice.'"/>'.$$initpage{$choice}.'&nbsp;&nbsp;</nobr>');
    }
    $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 %userenv = &Apache::lonnet::get('environment',['course_init_display']);
    my $control;
    if ($current eq '') {
        $control = 'userpref';
        if (exists($userenv{'firstres'})) {
            $current = 'firstres';
        } else {
            $current = 'whatsnew';
        }
    } else {
        $control = 'coursespecific';
    }
    return ($control,$current);
}

sub display_launcher {
    my ($r,$action,$refpage,$checkallowed,$tabbg,$rowColor1,$rowColor2,$show,
        $headings,$res_title,$tograde,$ungraded,$bombs,$bombed,$changed,
        $warnings,$triggered,$newdiscussions,$unread,$msgcount,$newmsgs,
                          $critmsgcount,$critmsgs,$interval,$countunread) = @_;

    if ($$checkallowed{$action}) {
        &start_box($r,$tabbg,$show,$headings,$action,$refpage);
        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,$refpage,$warnings,$triggered,
                                             $res_title,$rowColor1,$rowColor2);
            } elsif ($action eq 'coursediscussion') { # UNREAD COURSE DISCUSSION
                &display_coursediscussion($r,$newdiscussions,$unread,
                                $countunread,$res_title,$rowColor1,$rowColor2);
            } 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,$changed,$newdiscussions,
        $tograde,$bombs,$warnings,$rowColor1,$rowColor2,$threshold,$cdom,$crs,
                                 $res_title,$show,$starttime,$countunread) = @_;
    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 %lastreadtime;
    my %resourcetracker;
    my $discussiontime;

# Resource version changes
    if ($$show{'versionchanges'}) {
        &checkversions($cdom,$crs,$navmap,$changed,$starttime);
    }

    if ($$show{'coursediscussion'}) {   
        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}} = ();
        %{$$ungraded{$symb}} = ();
        %{$$triggered{$symb}} = ();
        $$triggered{$symb}{numparts} = 0;
        my $title = $resource->compTitle();
        $$res_title{$symb} = $title;
        my $ressymb = $resource->wrap_symb();

# Check if there are unread discussion postings
        if ($$show{'coursediscussion'}) {
            &check_discussions($cdom,$crs,$resource,$symb,$ressymb,$title,
                                                      $newdiscussions,$unread);
        }

# Check for ungraded problems
        if ($resource->is_problem()) {
            if ($$show{'handgrading'}) {
                &check_handgraded($resource,$symb,$title,$cdom,$crs,$ungraded,
                                                                     $tograde);
            }
        }

# Check for bombs
        if ($$show{'haserrors'}) {
            &check_bombed($resource,$symb,$title,$bombs,$bombed);
        }

# Maxtries and degree of difficulty for problem parts, unless handgradeable
        if ($$show{'abovethreshold'}) {  
            &check_thresholds($resource,$symb,\%resourcetracker,$triggered,
                       $threshold,$warnings,$warningnum,$rowColor1,$rowColor2);
        }

    }
    my $hasdiscussion = @{$newdiscussions};
    if ($$show{'coursediscussion'} && $hasdiscussion) { # Get time of last post; 
        $discussiontime = $navmap->{DISCUSSION_TIME};
        foreach my $ressymb (@{$newdiscussions}) {
            $$unread{$ressymb}{'lastpost'} = $$discussiontime{$ressymb};
        }
        if ($countunread eq 'on') { #Get count of unread postings for each resource 
            my $discussiondata = $navmap->get_discussion_data();
            foreach my $ressymb (@{$newdiscussions}) {
                &get_discussions($cdom,$crs,$discussiondata,$ressymb,
                                                       $unread,\%lastreadtime);
            }
        }
    }
}

sub check_discussions {
    my ($cdom,$crs,$resource,$symb,$ressymb,$title,$newdiscussions,
                                                                 $unread) = @_;
    if ($resource->hasDiscussion()) {
        %{$$unread{$ressymb}} = ();
        $$unread{$ressymb}{'title'} = $title;
        $$unread{$ressymb}{'symb'} = $symb;
        push(@{$newdiscussions}, $ressymb);
    }
}

sub get_discussions {
    my ($cdom,$crs,$discussiondata,$ressymb,$unread,$lastreadtime) = @_;
    my $prevread = 0;
    my $unreadcount = 0;
    if (defined($$lastreadtime{$ressymb})) {
        $prevread = $$lastreadtime{$ressymb};
    }
    my $version = $$discussiondata{'version:'.$ressymb};
    if ($version) {
        my $hiddenflag = 0;
        my $deletedflag = 0;
        my ($hidden,$deleted);
        for (my $id=$version; $id>0; $id--) {
            my $vkeys=$$discussiondata{$id.':keys:'.$ressymb};
            my @keys=split(/:/,$vkeys);
            if (grep/^hidden$/,@keys) {
                unless ($hiddenflag) {
                    $hidden = $$discussiondata{$id.':'.$ressymb.':hidden'};
                    $hiddenflag = 1;
                }
            } elsif (grep/^deleted$/,@keys) {
                unless ($deletedflag) {
                    $deleted = $$discussiondata{$id.':'.$ressymb.':deleted'};
                    $deletedflag = 1;
                }
            } else {
                unless (($hidden =~/\.$id\./) || ($deleted =~/\.$id\./)) {
                    if ($prevread <$$discussiondata{$id.':'.$ressymb.':timestamp'}) {
                        $unreadcount ++;
                        $$unread{$ressymb}{$unreadcount} = $id.': '.
                                 $$discussiondata{$id.':'.$ressymb.':subject'};
                    }
                }
            }
        }
        $$unread{$ressymb}{'unreadcount'} = $unreadcount;
    }
}


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 ($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;
                push(@{$tograde}, $symb);
            }
        }
    }
}

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});
            }
            $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>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 ++;
    }
}


sub get_curr_thresholds {
    my ($threshold,$uname,$udom,$cid,$cdom,$crs) = @_;
    my %thresholdsettings = &Apache::lonnet::dump('nohist_whatsnew',$udom,
                                                     $uname,$cid.':threshold');
    my $thresholdcount = 0;
    my ($tmp) = %thresholdsettings;
    unless ($tmp =~ /^Error/) {
        foreach my $item (keys %{$threshold}) { 
            if (exists($thresholdsettings{$cid.':threshold_'.$item})) {
                $$threshold{$item} = 
                             $thresholdsettings{$cid.':threshold_'.$item};
                $thresholdcount ++;
            }
        }
    }
    if ($thresholdcount == 3) {
        return;
    }
    my %coursesettings = &Apache::lonnet::dump('environment',
                                              $cdom,$crs,'internal.threshold');
    my ($temp) = %coursesettings;
    unless ($temp =~ /^Error/) {  
        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;
    if ($tmp =~ /^Error/) {
        &logthis('Error retrieving '.$caller.' setting from nohist_whatsnew for '.
                                                 $uname.";".$udom.' in '.$cid);
    } else {
        $currvalue = $settings{$cid.':'.$caller};
    }
    return $currvalue;
}

sub process_reset {
    my ($dom,$crs) = @_;
    my $result = '<b>'.&mt('Counters reset for following problems (and parts):').
                           '</b><br />';
    my @agg_types = ('attempts','users','correct');
    my %agg_titles = &Apache::lonlocal::texthash (
                     attempts => 'Number of submissions',
                     users => 'Students with submissions',
                     correct => 'Number of correct submissions',
                     );
    my @resets = ();
    my %titles = ();
    foreach my $key (keys(%env)) {
        next if ($key !~ /^form\.reset_(.+)$/);
        my $title = &Apache::lonnet::unescape($env{'form.title_'.$1});
        my $reset_item = &Apache::lonnet::unescape($1);
        my %curr_aggregates = &Apache::lonnet::dump('nohist_resourcetracker',$dom,$crs,$reset_item);
        my %aggregates = ();
        my ($symb,$part) = split(/\0/,$reset_item);
        foreach my $type (@agg_types) {
            $aggregates{$reset_item."\0".$type} = 0;
        }  
	$aggregates{$reset_item."\0".'resettime'} = time;
        my $putresult = &Apache::lonnet::put('nohist_resourcetracker',\%aggregates,
                          $dom,$crs);
        if ($putresult eq 'ok') {
            $result .= $title.' -part '.$part.': ';
            my %new_aggregates = &Apache::lonnet::dump('nohist_resourcetracker',$dom,$crs,$reset_item);
            foreach my $type (@agg_types) {
                $result .= $agg_titles{$type}.' = '.$new_aggregates{$reset_item."\0".$type}.'; ';
            }
            $result =~ s/; $//;
            $result .= '<br />';
        } else {
            $result = $title.' -part '.$part.': '.&mt('Unable to reset counters to zero due to [_1]',$putresult).'.<br />'."\n";
        }
    }
    return $result;
}

sub process_update {
    my ($uname,$udom,$threshold_titles) = @_;
    my $setoutput = '<b>Changes to threshold(s) for problem tracking:</b><br />';
    foreach (keys %env) {
        next if ($_!~/^form\.(.+)\_setparmval$/);
        my $name  = $1;
        my $value = $env{'form.'.$name.'_value'};
        if ($name && defined($value)) {
            my $put_result = &Apache::lonnet::put('nohist_whatsnew',
                                                  {$name=>$value},$udom,$uname);
           
            my ($shortname) = ($name =~ /^\Q$env{'request.course.id'}\E:threshold_(.+)$/);
            if ($put_result eq 'ok') {
                $setoutput.=&mt('Set threshold for [_1] to [_2]',
				'<b>'.$$threshold_titles{$shortname}.'</b>',
				'<b>'.$value.'</b>').'<br />';
	    } else {
                $setoutput.=&mt('Unable to set threshold for [_1] to [_2] due to [_3].',
				'<b>'.$name.'</b>','<b>'.$value.'</b>',
				'<tt>'.$put_result.'</tt>').'<br />';
            }
        }
    }
    return $setoutput;
}

sub getnormalmail {
    my ($newmsgs) = @_;
# Check for unread mail in course
    my $msgcount = 0;

    my @messages = sort(&Apache::lonnet::getkeys('nohist_email'));
    foreach my $message (@messages) {
	my $msgid=&Apache::lonnet::escape($message);
        my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)=
            &Apache::lonmsg::unpackmsgid($msgid);
        if (($fromcid) && ($fromcid eq $env{'request.course.id'})) {
            if (defined($sendtime) && $sendtime!~/error/) {
                my $numsendtime = $sendtime;
                $sendtime = &Apache::lonlocal::locallocaltime($sendtime);
                if ($status eq 'new') {
                    $msgcount ++;
                    if ($shortsubj eq '') {
                        $shortsubj = &mt('No subject');
                    }
                    $shortsubj = &Apache::lonnet::unescape($shortsubj);
                    push(@{$newmsgs}, {
                        msgid    => $msgid,
                        sendtime => $sendtime,
                        shortsub => $shortsubj,
                        from     => $fromname,
                        fromdom  => $fromdom
                        });
                }
            }
        }
    }
    return $msgcount;
}

sub getcritmail {
    my ($critmsgs) = @_; 
# Check for critical messages in course
    my %what=&Apache::lonnet::dump('critical');
    my $result = '';
    my $critmsgcount = 0;
    foreach my $msgid (sort(keys(%what))) {
        my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)=
            &Apache::lonmsg::unpackmsgid($msgid);
        if (($fromcid) && ($fromcid eq  $env{'request.course.id'})) {
            if (defined($sendtime) && $sendtime!~/error/) {
                my $numsendtime = $sendtime;
                $sendtime = &Apache::lonlocal::locallocaltime($sendtime);
                $critmsgcount ++;
                if ($shortsubj eq '') {
                    $shortsubj = &mt('No subject');
                }
                $shortsubj = &Apache::lonnet::unescape($shortsubj);
                push(@{$critmsgs}, {
                        msgid    => $msgid,
                        sendtime => $sendtime,
                        shortsub => $shortsubj,
                        from     => $fromname,
                        fromdom  => $fromdom
                        });
            }
        }
    }
    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');
                    $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,$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,$refpage,$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" action="/adm/whatsnew">'.
                ' <input type="hidden" name="command" value="reset" />'."\n".
                ' <input type="hidden" name="refpage" value="'.$refpage.'" />'.
                "\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,$countunread,$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',
                'tmlp' => 'Time of last post', 
    );
    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>');
        if ($countunread eq 'on') {
            $r->print('<td><b><small>'.$lt{'tmlp'}.'</small></b></td>'.
                      '<td align="right"><b><small>'.$lt{'numn'}.
                      '</small></b></td>');
        } else {
            $r->print('<td align="right"><b><small>'.$lt{'tmlp'}.
                         '</small></b></td>');
        }
        $r->print("</tr>\n");
        @{$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';
            }
            if ($rowNum %2 == 1) {
                $rowColor = $rowColor1;
            } else {
                $rowColor = $rowColor2;
            }
            my $lastpost = &Apache::lonnavmaps::timeToHumanString(
                                               $$unread{$ressymb}{'lastpost'});
            $r->print('<tr bgcolor="'.$rowColor.'"><td><small><a href="'.$feedurl.'?symb='.$$unread{$ressymb}{symb}.'">'.$forum_title.'</a>&nbsp;</td><td><small>'.$type.'&nbsp;</small></td>');
            if ($countunread eq 'on') {
                my $unreadnum = $$unread{$ressymb}{'unreadcount'};
                $r->print('<td><small>'.$lastpost.'<small></td><td align="right">'.
                          '<small>',$unreadnum.'&nbsp;</small></td>');
            } else {
                $r->print('<td align="right"><small>'.$lastpost.'</small></td>');
            }
            $r->print("</tr>\n");
            $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 {
    my ($a,$b,$res_title) = @_;
    my ($atitle,$btitle) = (lc($$res_title{$a}),lc($$res_title{$b}));
    $atitle=~s/^\s*//;
    $btitle=~s/^\s*//;
    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=~/^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 store_display_settings {
    my ($uname,$udom,$cid,$checkallowed) = @_;
    my %whatsnew_settings;
    my $result;
    foreach my $key (keys(%{$checkallowed})) {
        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;
    if (defined($env{'form.interval'})) {
        $interval_settings{$cid.':interval'} = $env{'form.interval'};
        my $outcome = &Apache::lonnet::put('nohist_whatsnew',
                                             \%interval_settings,$udom,$uname);
        if ($outcome eq 'ok') {
            $result = &mt('Interval set to version changes [_1]',
                  '<b>'.$$interval_titles{$env{'form.interval'}}.'</b><br />');

        } else {
            &Apache::lonnet::logthis('Error storing whatsnew interval setting'.
                     ' '.$outcome.' for '.$uname.':'.$udom.' in course '.$cid);
            $result = &mt('Unable to set interval to [_1] due to [_2].',
                         '<b>'.$$interval_titles{$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>'.$env{'form.countunread'}.'</b><br />');
                                                                                  
        } else {
            &Apache::lonnet::logthis('Error storing whatsnew countunread setting'.
                     ' '.$outcome.' for '.$uname.':'.$udom.' in course '.$cid);
            $result = &mt('Unable to set "number unread posts display" to [_1]'.
                          ' due to [_2].',
                         '<b>'.$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 $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 course now set by [_1]',"<b>user's global preferences</b>.");
                } else {
                    $result = &mt('Page displayed after role selection in this course set to [_1]','<b>'.$$initpage{$env{'form.courseinit_page'}}.'</b>.');
                }
            } else {
                &Apache::lonnet::logthis('Error storing whatsnew courseinit '.
                                         'setting: '.$outcome.' for '.$uname.
                                                 ':'.$udom.' in course '.$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 course to [_1] due to [_2].',
                         '<b>'.$$initpage{$env{'form.courseinit_page'}}.'</b>',
                         '<tt>'.$outcome.'</tt>.<br />');
                }
            }
        }
    }
    return $result;
}

sub start_box {
    my ($r,$tabbg,$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'".');">Hide</a></b>';
   
    } else {
        $showhide = '<b><a href="javascript:change_display(document.visible.'.
                               '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&refpage='.$refpage.'"><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&refpage='.$refpage.'"><b><small>'.$lt{'chin'}.'</small></b></a></td>
              </tr>');
     } elsif ($caller eq 'coursediscussion') {
         $r->print('
              <tr>
                <td bgcolor="'.$tabbg.'" align="right"><a href="/adm/whatsnew?command=chgdisc&refpage='.$refpage.'"><b><small>'.$lt{'chop'}.'</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;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>