File:  [LON-CAPA] / loncom / interface / lonwhatsnew.pm
Revision 1.67: download - view: text, annotated - select for diffs
Wed Dec 20 23:02:33 2006 UTC (17 years, 5 months ago) by raeburn
Branches: MAIN
CVS tags: version_2_3_X, version_2_3_2, version_2_3_1, version_2_3_0, HEAD
Renaming unread_discussion() as discussion_info() and making the funtion more universally useful.  Can now be used to retrieve counts for all postings, or just unread postings (if 'unread') is included as an argumnet in the call (e.g., $resource->discussion_info('unread');).  Also if
called in array context, returns ($count,%info), where %info is a hash of a hash.  Outer hash keys are count number, inner hash keys are: subject, id, timestamp.

    1: #
    2: # $Id: lonwhatsnew.pm,v 1.67 2006/12/20 23:02:33 raeburn Exp $
    3: #
    4: # Copyright Michigan State University Board of Trustees
    5: #
    6: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    7: #
    8: # LON-CAPA is free software; you can redistribute it and/or modify
    9: # it under the terms of the GNU General Public License as published by
   10: # the Free Software Foundation; either version 2 of the License, or
   11: # (at your option) any later version.
   12: #
   13: # LON-CAPA is distributed in the hope that it will be useful,
   14: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16: # GNU General Public License for more details.
   17: #
   18: # You should have received a copy of the GNU General Public License
   19: # along with LON-CAPA; if not, write to the Free Software
   20: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21: #
   22: # /home/httpd/html/adm/gpl.txt
   23: #
   24: # http://www.lon-capa.org/
   25: #
   26: 
   27: 
   28: package Apache::lonwhatsnew;
   29: 
   30: use strict;
   31: use lib qw(/home/httpd/lib/perl);
   32: use Apache::lonnet;
   33: use Apache::loncommon();
   34: use Apache::lonhtmlcommon();
   35: use Apache::lonlocal;
   36: use Apache::loncoursedata();
   37: use Apache::lonnavmaps();
   38: use Apache::lonuserstate;
   39: use Apache::Constants qw(:common :http);
   40: use Time::Local;
   41: use GDBM_File;
   42: use lib '/home/httpd/lib/perl/';
   43: use LONCAPA;
   44: 
   45: #----------------------------
   46: # handler
   47: #
   48: #----------------------------
   49: 
   50: sub handler {
   51:     my $r = shift;
   52:     if ($r->header_only) {
   53:         &Apache::loncommon::content_type($r,'text/html');
   54:         $r->send_http_header;
   55:         return OK;
   56:     }
   57:     &Apache::loncommon::get_unprocessed_cgi(
   58:                                    $ENV{'QUERY_STRING'},['command','refpage']);
   59: 
   60:     my $command = $env{'form.command'};
   61:     my $refpage = $env{'form.refpage'};
   62: 
   63:     my %checkallowed = ( coursenormalmail => 1,
   64: 			 coursecritmail => 1, );
   65:     foreach my $perm_check (['whn','whatsnew',1],
   66: 			    ['pch','coursediscussion',1],
   67: 			    ['mgr','handgrading',1],
   68: 			    ['vgr','abovethreshold',1],
   69: 			    ['opa','haserrors',1],
   70: 			    ['mdc','versionchanges',0],
   71: 			    ) {
   72: 	my ($perm,$key,$check_section) = @{ $perm_check };
   73: 	my $scope = $env{'request.course.id'};
   74: 	if (!($checkallowed{$key} = &Apache::lonnet::allowed($perm,$scope))) {
   75: 	    $scope .= '/'.$env{'request.course.sec'};
   76: 	    if ( $check_section ) {
   77: 		$checkallowed{$key} = &Apache::lonnet::allowed($perm,$scope);
   78: 	    }
   79: 	    if ($checkallowed{$key}) {
   80: 		$checkallowed{$key.'_section'} = $env{'request.course.sec'};
   81: 	    }
   82: 	}
   83:     }
   84: 
   85:     if ( ! $env{'request.course.fn'} || ! $checkallowed{'whatsnew'}) {
   86:         # Not in a course, or no whn priv in course
   87:         $env{'user.error.msg'}="/adm/whatsnew::whn:0:0:Cannot display what's new page";
   88:         return HTTP_NOT_ACCEPTABLE;
   89:     }
   90: 
   91:     &Apache::loncommon::content_type($r,'text/html');
   92:     $r->send_http_header;
   93: 
   94:     $r->print(&display_header($command,\%checkallowed));
   95: 
   96:     &Apache::lonhtmlcommon::clear_breadcrumbs();
   97:     &Apache::lonhtmlcommon::add_breadcrumb
   98:             ({href=>'/adm/whatsnew',
   99:               text=>"Display Action Items"});
  100:     if (($command eq 'chgthreshold') && $checkallowed{'abovethreshold'}) {
  101:         &Apache::lonhtmlcommon::add_breadcrumb
  102:             ({href=>'/adm/whatsnew?command=chgthreshold&refpage='.$refpage,
  103:               text=>"Change thresholds"});
  104:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
  105:             ("What's New?",#'Course_Action_Items_Thresholds'
  106: 	     ));
  107:     } elsif (($command eq 'chginterval') && $checkallowed{'versionchanges'} ) {
  108:         &Apache::lonhtmlcommon::add_breadcrumb
  109:             ({href=>'/adm/whatsnew?command=chginterval&refpage='.$refpage,
  110:               text=>"Change interval"});
  111:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
  112:             ("What's New?",#'Course_Action_Items_Intervals'
  113: 	     ));
  114:     } elsif (($command eq 'chgdisc') && $checkallowed{'coursediscussion'}) {
  115:         &Apache::lonhtmlcommon::add_breadcrumb
  116:             ({href=>'/adm/whatsnew?command=chgdisc&refpage='.$refpage,
  117:               text=>"Change discussion display"});
  118:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
  119:             ("What's New?",#'Course_Action_Items_Intervals'
  120: 	     ));
  121:     } elsif ($command eq 'courseinit') {
  122:         &Apache::lonhtmlcommon::add_breadcrumb
  123:             ({href=>'/adm/whatsnew?command=courseinit&refpage='.$refpage,
  124:               text=>"Course initialization preference"});
  125:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
  126:             ("What's New?",#'Course_Action_Items_Initialization'
  127: 	     ));
  128:     } else {
  129:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
  130:             ("What's New?",#'Course_Action_Items_Display'
  131: 	     ));
  132:     }
  133:     &display_main_box($r,$command,$refpage,\%checkallowed);
  134:     return OK;
  135: }
  136: 
  137: #------------------------------
  138: # display_main_box
  139: #
  140: # Display all the elements within the main box
  141: #------------------------------
  142:                                                                                 
  143: sub display_main_box {
  144:     my ($r,$command,$refpage,$checkallowed) = @_;
  145:     my $domain=&Apache::loncommon::determinedomain();
  146:     my $function = &Apache::loncommon::get_users_function();
  147:     my $tabbg=&Apache::loncommon::designparm($function.'.tabbg',$domain);
  148:     my $lctype = lc(&Apache::loncommon::course_type());
  149:     $r->print('<table width="100%" border="0" cellpadding="5" cellspacing="0"><tr><td width="100%">');
  150: 
  151:     my %threshold_titles = &Apache::lonlocal::texthash (
  152:                          av_attempts => 'Average number of attempts',
  153:                          degdiff => 'Degree of difficulty',
  154:                          numstudents => 'Total number of students with submissions',
  155:     );
  156: 
  157:     my %interval_titles = &Apache::lonlocal::texthash (
  158:                             -1 => "since start of $lctype",
  159:                        2592000 => 'since last month',
  160:                         604800 => 'since last week',
  161:                          86400 => 'since yesterday',
  162:     );
  163: 
  164:     my %initpage = &Apache::lonlocal::texthash (
  165:                      firstres => "first resource in the $lctype",
  166:                      whatsnew => "what's new? page",
  167:                      userpref => 'your general user preferences',
  168:                      coursespecific => "specific setting for this $lctype",
  169:                    );
  170:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
  171:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
  172: 
  173:     if (($command eq 'chgthreshold') 
  174: 	&& $checkallowed->{'abovethreshold'}) {
  175:         &display_threshold_config($r,$refpage,$tabbg,\%threshold_titles,
  176:                                                                    $cdom,$crs);
  177:     } elsif (($command eq 'chginterval') 
  178: 	     && $checkallowed->{'versionchanges'}) {
  179:         &display_interval_config($r,$refpage,\%interval_titles);
  180:     } elsif (($command eq 'chgdisc') 
  181: 	     && $checkallowed->{'coursediscussion'}) {
  182:         &display_discussion_config($r,$refpage);
  183:     } elsif ($command eq 'courseinit') {
  184:         &courseinit_config($r,$refpage,\%initpage);
  185:     } else {
  186:         &display_actions_box($r,$tabbg,$command,$refpage,\%threshold_titles,
  187:                         \%interval_titles,\%initpage,$cdom,$crs,$checkallowed);
  188:     }
  189:     my $end_page = &Apache::loncommon::end_page();
  190:     $r->print(<<END_OF_BLOCK);
  191:   </td>
  192:  </tr>
  193: </table><br />
  194: $end_page
  195: END_OF_BLOCK
  196: }
  197: 
  198: #-------------------------------
  199: # display_header
  200: #
  201: # Display the header information and set
  202: # up the HTML
  203: #-------------------------------
  204: 
  205: sub display_header {
  206:     my ($command,$checkallowed) = @_;
  207:     
  208:     my $scripttag;
  209:     unless ($command eq 'chgthreshold' || $command eq 'chginterval') {
  210:        $scripttag = <<"END";
  211: <script type="text/javascript">
  212: function change_display(caller,change) {
  213:     caller.value = change;
  214:     document.visible.submit(); 
  215: }
  216: 
  217: function changeAll(change) {
  218: END
  219:         foreach my $item (keys(%{$checkallowed})) {
  220: 	    if ($item =~ /_section$/) { next; }
  221:             if ($$checkallowed{$item}) {
  222:                 $scripttag.='document.visible.display_'.$item.'.value=change'.
  223:                             "\n";
  224:             }
  225:         }
  226:         $scripttag.='document.visible.submit();
  227: }
  228: </script>
  229: ';
  230:     }
  231:     my $course_type=&Apache::loncommon::course_type();
  232:     return &Apache::loncommon::start_page($course_type.' Action Items',
  233: 					  $scripttag);
  234: }
  235: 
  236: #-------------------------------
  237: # display_actions_box
  238: #
  239: # Display the action items
  240: #
  241: #-------------------------------
  242:                                                                                 
  243: sub display_actions_box {
  244:     my ($r,$tabbg,$command,$refpage,$threshold_titles,$interval_titles,
  245:                                       $initpage,$cdom,$crs,$checkallowed) = @_;
  246:     my $rowColor1 = "#ffffff";
  247:     my $rowColor2 = "#eeeeee";
  248: 
  249:     my $udom = $env{'user.domain'};
  250:     my $uname = $env{'user.name'};
  251:     my $cid = $env{'request.course.id'};
  252:     my $crstype = &Apache::loncommon::course_type();
  253:     my $lctype = lc($crstype);
  254:     my %stulabel = (
  255:                     'Course' => 'students',
  256:                     'Group' => 'members',
  257:                    );
  258:     my %lt = &Apache::lonlocal::texthash(
  259:                  'yacc' => 'You are accessing an invalid course',
  260:                  'gtfr' => 'Go to first resource',
  261:                  'hial' => 'Hide all',
  262:                  'shal' => 'Show all',
  263:     );
  264: 
  265:     my %unread = ();
  266:     my %ungraded = ();
  267:     my %bombed = ();
  268:     my %triggered = ();
  269:     my %changed = ();
  270:     my @newmsgs = ();
  271:     my @critmsgs = ();
  272:     my @newdiscussions = ();
  273:     my @tograde = ();
  274:     my @bombs = ();
  275:     my @warnings = ();
  276:     my $msgcount = 0;
  277:     my $critmsgcount = 0;
  278: 
  279:     my %res_title = ();
  280:     my %show = ();
  281:     my $needitems = 0;
  282:     my $boxcount = 0;
  283: 
  284:     my $result;
  285:     if ($command eq 'newcourseinit') {
  286:         $result = &store_courseinit_setting($uname,$udom,$cid,$initpage);
  287:     }
  288: 
  289:     my %threshold = ();
  290:     my %pagedesc = &Apache::lonlocal::texthash (
  291:                      firstres => 'First resource',
  292:                      whatsnew => "What's New? page",
  293:                      userpref => 'user preference',
  294:                      coursespecific => $lctype.' only',
  295:                      default => 'default',
  296:                    );
  297: 
  298:     my ($initcontrol,$initdisp) = &curr_courseinit();
  299:     my $currinit = $pagedesc{$initdisp}.' ('.$pagedesc{$initcontrol}.')';
  300: 
  301:     unless ($cid) {
  302:         $r->print('<br /><b><center>'.$lt{'yacc'}.'</center></b><br /><br />');
  303:         return;
  304:     }
  305: 
  306:     if ($refpage eq 'start') {
  307:         if (tie(my %bighash,'GDBM_File',$env{'request.course.fn'}.'.db',
  308:             &GDBM_READER(),0640)) {
  309:             my $furl=$bighash{'first_url'};
  310:             untie(%bighash);
  311:             $r->print('<font size="+1"><a href="'.$furl.'">'.$lt{'gtfr'}.
  312:                   '</a></font><br />');
  313:         }
  314:     }
  315:     $r->print(&mt('Page set to be displayed after you have selected a role in this '.$lctype).
  316:               '. <nobr>'.&mt('Currently: <i>[_1]</i>',$currinit).'.&nbsp;&nbsp;'.
  317:               &mt('<b>Change</b> for just <a href="/adm/whatsnew?command=courseinit&refpage=[_1]">this '.$lctype.'</a>',$refpage).' '.
  318:               &mt('or for all <a href="/adm/preferences?action=changecourseinit&refpage=[_1]">your courses</a>',$refpage).'</nobr><br /><hr />');
  319: 
  320:     if ($command eq 'reset') {
  321:         $result = &process_reset($cdom,$crs);
  322:     } elsif ($command eq 'update') {
  323:         $result = &process_update($uname,$udom,$threshold_titles);
  324:     } elsif ($command eq 'newinterval') {
  325:         $result = &store_interval_setting($uname,$udom,$cid,$interval_titles);
  326:     } elsif ($command eq 'newdiscconf') {
  327:         $result = &store_discussion_setting($uname,$udom,$cid);
  328:     }
  329: 
  330:     my $store_result=&store_display_settings($uname,$udom,$cid,$checkallowed);
  331: 
  332:     unless ($store_result eq 'ok') { 
  333:         &Apache::lonnet::logthis('Error storing whatsnew settings: '.
  334:             $store_result.' for '.'user '.$uname.':'.$udom.' in '.$lctype.' '.$cid);
  335:         $result .= &mt('Unable to store visibility settings due to [_1]',
  336:                        $store_result); 
  337:     }
  338: 
  339:     if ($result) {
  340:         $r->print($result.'<hr width="100%" />');
  341:     }
  342:     $r->rflush();
  343: 
  344: 
  345:     my %display_settings = &get_display_settings($uname,$udom,$cid);
  346:     my $timediff = $display_settings{$cid.':interval'};
  347:     unless (defined($timediff)) { $timediff = 604800; } 
  348:     my $now = time;
  349:     my $interval = $$interval_titles{$timediff};
  350:     if ($timediff == -1) {
  351:         $timediff = time;
  352:     } 
  353:     my $starttime = $now - $timediff;
  354:     my $countunread = $display_settings{$cid.':countunread'};
  355:     unless (defined($countunread)) {
  356:         $countunread = 'on';
  357:     }
  358: 
  359:     my %headings = &Apache::lonlocal::texthash(
  360:                 coursediscussion =>  'Unread '.$lctype.' discussion posts',
  361:                 handgrading =>  'Problems requiring handgrading',
  362:                 haserrors => 'Problems with errors',
  363:                 versionchanges => 'Resources in '.$lctype.' with version changes '.$interval,
  364:                 coursenormalmail => 'New '.$lctype.' messages',
  365:                 coursecritmail => 'New critical messages in '.$lctype,
  366:     );
  367: 
  368:     if ($$checkallowed{'abovethreshold'}) {
  369:         &get_curr_thresholds(\%threshold,$uname,$udom,$cid,$cdom,$crs);
  370:     }
  371: 
  372:     $headings{'abovethreshold'} = 
  373: 	&mt('Problems with av. attempts &ge; [_1] or deg. difficulty &ge; [_2] <br /> and total number of '.$stulabel{$crstype}.' with submissions &ge; [_3]',
  374: 	    $threshold{'av_attempts'},$threshold{'degdiff'},
  375: 	    $threshold{'numstudents'});
  376: 
  377:     my @actionorder = ('handgrading','haserrors','abovethreshold','versionchanges','coursediscussion','coursenormalmail','coursecritmail');
  378: 
  379:     foreach my $key (keys(%{$checkallowed})) {
  380: 	if ($key =~ /_section$/) { next; }
  381:         $show{$key} = 0;
  382:         if ($$checkallowed{$key}) {
  383:             unless ($display_settings{$cid.':'.$key} eq 'hide') {
  384:                 $show{$key} = 1;
  385:             }
  386:         }
  387:     }
  388: 
  389:     foreach my $item (@actionorder) {
  390:         unless ($item eq 'coursenormalmail' || $item eq 'coursecritmail') {
  391:             if ($show{$item}) {
  392:                 $needitems = 1;
  393:                 last;
  394:             }
  395:         }
  396:     }
  397: 
  398:     if ($needitems) {
  399:         &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\%changed,\@newdiscussions,\@tograde,\@bombs,\@warnings,$rowColor1,$rowColor2,\%threshold,$cdom,$crs,\%res_title,\%show,$starttime,$countunread);
  400:     }
  401:     if ($show{'coursenormalmail'}) {
  402:         $msgcount = &getnormalmail(\@newmsgs);
  403:     }
  404:     if ($show{'coursecritmail'}) {
  405:         $critmsgcount = &getcritmail(\@critmsgs);
  406:     }
  407: 
  408:     $r->print(qq|<a href="javascript:changeAll('hide');">$lt{'hial'}</a>
  409:      &nbsp;&nbsp;<a href="javascript:changeAll('show');">$lt{'shal'}</a>
  410:      <form method="post" name="visible" action="/adm/whatsnew">\n|);
  411:     foreach my $item (keys(%{$checkallowed})) {
  412: 	if ($item =~ /_section$/) { next; }
  413:         if ($$checkallowed{$item}) {
  414:             $r->print('<input type="hidden" name="display_'.$item.'" />'."\n");
  415:         }
  416:     }
  417: 
  418:     $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%">');
  419: 
  420:     my $displayed = 0;
  421:     my $totalboxes = 0;
  422:     foreach my $key (keys(%{$checkallowed})) {
  423: 	if ($key =~ /_section$/) { next; }
  424: 	if ($key eq 'whatsnew' ) { next; } # whatsnew check creates no box
  425:         if ($$checkallowed{$key}) {
  426:             $totalboxes ++;
  427:         }
  428:     }
  429:     my $halfway = int($totalboxes/2) + $totalboxes%2;
  430:     foreach my $actionitem (@actionorder) {
  431:         if ($$checkallowed{$actionitem}) {
  432:             if ($displayed == $halfway) {
  433:                 $r->print('</td><td width="6%">&nbsp;</td><td align="left" valign="top" width="47%">');
  434:             }
  435:             &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);
  436:             $displayed ++; 
  437:         }
  438:     }
  439:     $r->print('
  440:            </table>
  441:           </td>
  442:          </tr>
  443:         </table>
  444:       </td>
  445:     </tr>
  446:    </table>');
  447: }
  448: 
  449: #-------------------------------
  450: # display_threshold_config
  451: #
  452: # Display the threshold setting screen 
  453: #
  454: #-------------------------------
  455:                                                                                 
  456: sub display_threshold_config {
  457:     my ($r,$refpage,$tabbg,$threshold_titles,$cdom,$crs) = @_;
  458:     my $uname = $env{'user.name'};
  459:     my $udom = $env{'user.dom'};
  460:     my $cid = $env{'request.course.id'};
  461:     my %threshold = ();
  462:     my $rowColor1 = "#ffffff";
  463:     my $rowColor2 = "#eeeeee";
  464:     my $rowColor;
  465: 
  466:     my @thresholditems = ("av_attempts","degdiff","numstudents");
  467:     my %threshold_titles = &Apache::lonlocal::texthash(
  468:                          av_attempts => 'Average number of attempts',
  469:                          degdiff => 'Degree of difficulty',
  470:                          numstudents => 'Total number of students with submissions',
  471:                          );
  472:     &get_curr_thresholds(\%threshold,$uname,$udom,$cid,$cdom,$crs);
  473: 
  474:     $r->print('<br /><form name="thresholdform" method="post" action="/adm/whatsnew">
  475:         <table border="0" cellpadding="2" cellspacing="4">
  476:          <tr>
  477:           <td align="left" valign="top" width="45%">
  478:            <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000">
  479:             <tr>
  480:              <td>
  481:                <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000">
  482:                 <tr>
  483:                 <td bgcolor="#ffffff">
  484:                  <table cellspacing="0" cellpadding="4" border="0">
  485:      <tr bgcolor="'.$tabbg.'">
  486:       <th>Threshold Name</th>
  487:       <th>Current value</th>
  488:       <th>Change?</th>
  489:      </tr>');
  490:     my $rowNum =0;
  491:     foreach my $type (@thresholditems) {
  492:         my $parameter = $env{'request.course.id'}.':threshold_'.$type;
  493: # onchange is javascript to automatically check the 'Set' button.
  494:         my $onchange = 'onFocus="javascript:window.document.forms'.
  495:               "['thresholdform'].elements['".$parameter."_setparmval']".
  496:               '.checked=true;"';
  497:         if ($rowNum %2 == 1) {
  498:             $rowColor = $rowColor1;
  499:         } else {
  500:             $rowColor = $rowColor2;
  501:         }
  502:         $r->print('
  503:      <tr bgcolor="'.$rowColor.'">
  504:       <td>'.$threshold_titles{$type}.'</td>
  505:       <td>'.&Apache::lonhtmlcommon::textbox($parameter.'_value',
  506:                                             $threshold{$type},
  507:                                             10,$onchange).'</td>
  508:       <td>'
  509:            .&Apache::lonhtmlcommon::checkbox($parameter.'_setparmval').
  510:       '</td>
  511:      </tr>');
  512:         $rowNum ++;
  513:     }
  514:     $r->print('</table></td></tr></table></td></tr></table>
  515:            <br /><input type="submit" name="threshold" value="Make changes" />
  516:                  <input type="hidden" name="command" value="update" />
  517:                  <input type="hidden" name="refpage" value="'.$refpage.'" />
  518:                </form>');
  519: }
  520: 
  521: #-------------------------------
  522: # display_interval_config
  523: #
  524: # Display the interval setting screen
  525: #
  526: #-------------------------------
  527:                                                                                    
  528: sub display_interval_config {
  529:     my ($r,$refpage,$interval_titles) = @_;
  530:     my $lctype = lc(&Apache::loncommon::course_type());
  531:     my $current = &get_current($env{'user.name'},$env{'user.domain'},
  532:                                 $env{'request.course.id'},'interval');
  533:     $r->print('<br />'.&mt('Choose the time window to use for display of version changes for resources in the '.$lctype.'.'));
  534:     unless ($current eq '') {
  535:         $r->print(' '.&mt('Current value is [_1]','<b>'.
  536:                   $$interval_titles{$current}.'</b>.'));
  537:     }
  538:     $r->print('<br /><br />
  539: <form method="post" name="intervalswitch" action="/adm/whatsnew">
  540: <input type="hidden" name="command" value="newinterval" />
  541: <input type="hidden" name="refpage" value="'.$refpage.'" />
  542: <select name="interval">
  543: ');
  544:     foreach my $key (reverse sort ({$a cmp $b} (keys(%{$interval_titles})))) {
  545:         $r->print('<option value="'.$key.'">Version changes '.$$interval_titles{$key}.
  546:                   '</option>'."\n");
  547:     }
  548:     $r->print('</select>&nbsp;&nbsp;
  549:                <input type="submit" name="display" value="'.
  550:                &mt('Change interval').'" /></form>');
  551:     return;
  552: }
  553: 
  554: #----------------------------------------------
  555: # display_discussion_config
  556: #
  557: # Display the discussion display setting screen
  558: #
  559: #----------------------------------------------
  560:                                                                                   
  561: sub display_discussion_config {
  562:     my ($r,$refpage) = @_;
  563:     my $current = &get_current($env{'user.name'},$env{'user.domain'},
  564:                                 $env{'request.course.id'},'countunread');
  565:     if ($current eq '') {
  566:         $current = 'on';
  567:     }
  568:     my %opposite = ( 
  569:                       'on' => 'off',
  570:                       'off' => 'on',
  571:                     );
  572:     $r->print('<script type="text/javascript">
  573: function toggle_countunread(choice) {
  574:     if (choice == "unchanged") {
  575:         document.discussionswitch.command.value = "";
  576:     }
  577:     document.discussionswitch.submit();
  578: }
  579: </script>');
  580:     $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>'));
  581:     $r->print('<br /><br />
  582: <form method="post" name="discussionswitch" action="/adm/whatsnew">
  583: <input type="hidden" name="command" value="newdiscconf" />
  584: <input type="hidden" name="refpage" value="'.$refpage.'" />
  585: <input type="hidden" name="countunread" value="'.$opposite{$current}.'" />
  586: ');
  587:     $r->print('<br/>
  588:                <input type="button" name="display" value="'.
  589:                &mt('Change to [_1]',$opposite{$current}).'" 
  590:                onclick="javascript:toggle_countunread('."'change'".')" />
  591:                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp&nbsp;&nbsp;
  592:                <input type="button" name="nochange" value="'.
  593:                &mt("No change").'" 
  594:                onclick="javascript:toggle_countunread('."'unchanged'".')" />
  595:                </form>');
  596:     return;
  597: }
  598: 
  599: #---------------------------------------------------
  600: # courseinit_config
  601: #
  602: # Set page displayed when course loads after 
  603: # selecting a role in the course from the roles page. 
  604: #
  605: #---------------------------------------------------
  606: 
  607: sub courseinit_config {
  608:     my ($r,$refpage,$initpage) = @_;
  609:     my ($control,$current) = &curr_courseinit();
  610:     my @chgstate = ('userpref','coursespecific');
  611:     my @chgentry = ('firstres','whatsnew');
  612:     my $lctype = lc(&Apache::loncommon::course_type());
  613:     my %lt = &Apache::lonlocal::texthash(
  614:                              'chwp' => "Choose which page will be displayed when you enter this $lctype after selecting a role.",
  615:                              'cuva' => 'Current value is determined by',
  616:                              'anis' => 'and is set to display',
  617:                              'padc' => 'Page display controlled by',
  618:                              'chce' => 'Choose '.$lctype.' entry',
  619:                              'moce' => 'Modify '.$lctype.' entry',
  620:     );
  621:     $r->print(<<"END"); 
  622: <br />$lt{'chwp'}
  623: <br />$lt{'cuva'}: <b>
  624: $$initpage{$control}</b> $lt{'anis'} <b>
  625: $$initpage{$current}</b>.<br /><br />
  626: <form method="post" name="courseinitswitch" action="/adm/whatsnew">
  627: <input type="hidden" name="command" value="newcourseinit" />
  628: <input type="hidden" name="refpage" value="$refpage" />
  629: $lt{'padc'}:&nbsp;&nbsp;
  630: END
  631:     foreach my $choice (@chgstate) {
  632:         my $chkstring;
  633:         if ($choice eq $control) {
  634:             $chkstring = ' checked="checked" ';
  635:         }  
  636:         $r->print('<nobr><label><input type="radio" name="courseinit_control" value="'.
  637:                    $choice.'"'.$chkstring.'/>'.$$initpage{$choice}.
  638:                    '&nbsp;&nbsp;</label></nobr>');
  639:     }
  640:     $r->print('<br /><br />'.&mt('If').' '.$$initpage{'coursespecific'}.
  641:               ' - <br />'.$lt{'chce'}.": \n");
  642:     foreach my $choice (@chgentry) {
  643:         my $chkstring;
  644:         if (($choice eq $current) && ($control eq 'coursespecific')) {
  645:             $chkstring = ' checked="checked" ';
  646:         }
  647:         $r->print('<nobr><label><input type="radio" name="courseinit_page" value="'.
  648:                   $choice.'"'.$chkstring.'/>'.$$initpage{$choice}.
  649:                   '&nbsp;&nbsp;</label></nobr>');
  650:     }
  651:     $r->print('<br /><br /><input type="submit" name="display" value="'.
  652:                $lt{'moce'}.'" /></form>');
  653:     return;
  654: }
  655: 
  656: sub curr_courseinit {
  657:     my $current = &get_current($env{'user.name'},$env{'user.domain'},
  658:                                 $env{'request.course.id'},'courseinit');
  659:     my $control;
  660:     if ($current) {
  661:         $control = 'coursespecific';
  662:     } else {
  663:         $control = 'userpref';
  664:         my %userenv = &Apache::lonnet::get('environment',
  665:                                                       ['course_init_display']);
  666:         if (exists($userenv{'course_init_display'})) {
  667:             $current = $userenv{'course_init_display'};
  668:         }
  669:         unless ($current) {
  670:             $current = 'whatsnew';
  671:         }
  672:     }
  673:     return ($control,$current);
  674: }
  675: 
  676: sub display_launcher {
  677:     my ($r,$action,$refpage,$checkallowed,$tabbg,$rowColor1,$rowColor2,$show,
  678:         $headings,$res_title,$tograde,$ungraded,$bombs,$bombed,$changed,
  679:         $warnings,$triggered,$newdiscussions,$unread,$msgcount,$newmsgs,
  680:                           $critmsgcount,$critmsgs,$interval,$countunread) = @_;
  681: 
  682:     if ($$checkallowed{$action}) {
  683:         &start_box($r,$tabbg,$show,$headings,$action,$refpage,$action);
  684:         if ($$show{$action}) {
  685:             if ($action eq 'handgrading') {    # UNGRADED ITEMS
  686:                 &display_handgrade($r,$tograde,$rowColor1,$rowColor2,
  687:                                                                     $ungraded);
  688:             } elsif ($action eq 'haserrors') { # BOMBS
  689:                 &display_haserrors($r,$bombs,$rowColor1,$rowColor2,$bombed,
  690:                                                                    $res_title);
  691:             } elsif ($action eq 'versionchanges') { # VERSION CHANGES
  692:                 &display_versionchanges($r,$changed,$res_title,$rowColor1,
  693:                                                          $rowColor2,$interval);
  694: 
  695:             } elsif ($action eq 'abovethreshold') { # DEGDIFF/AV. TRIES TRIGGERS
  696:                 &display_abovethreshold($r,$refpage,$warnings,$triggered,
  697: 					$res_title);
  698:             } elsif ($action eq 'coursediscussion') { # UNREAD COURSE DISCUSSION
  699:                 &display_coursediscussion($r,$newdiscussions,$unread,
  700:                                 $countunread,$res_title,$rowColor1,$rowColor2);
  701:             } elsif ($action eq 'coursenormalmail') { # NORMAL MESSAGES
  702:                 &display_coursenormalmail($r,$msgcount,$newmsgs,$rowColor1,
  703:                                                                    $rowColor2);
  704:             } elsif ($action eq 'coursecritmail') { # CRITICAL MESSAGES
  705:                 &display_coursecritmail($r,$critmsgcount,$critmsgs,$rowColor1,
  706:                                                                    $rowColor2);
  707:             }
  708:         }
  709:         &end_box($r);
  710:     }
  711:     return;
  712: }
  713: 
  714: sub getitems {
  715:     my ($unread,$ungraded,$bombed,$triggered,$changed,$newdiscussions,
  716:         $tograde,$bombs,$warnings,$rowColor1,$rowColor2,$threshold,$cdom,$crs,
  717:                                  $res_title,$show,$starttime,$countunread) = @_;
  718:     my $navmap = Apache::lonnavmaps::navmap->new();
  719:     # force retrieve Resource to seed the part id cache we'll need it later
  720:     my @allres=$navmap->retrieveResources(undef,
  721:                      sub {if ($_[0]->is_problem) { $_[0]->parts();} return 1;});
  722:     my %resourcetracker;
  723:     my $discussiontime;
  724: 
  725: # Resource version changes
  726:     if ($$show{'versionchanges'}) {
  727:         &checkversions($cdom,$crs,$navmap,$changed,$starttime);
  728:     }
  729: 
  730:     if ($$show{'abovethreshold'}) {
  731:         %resourcetracker =  &Apache::lonnet::dump('nohist_resourcetracker',
  732:                                                                    $cdom,$crs);
  733:     }
  734: 
  735:     foreach my $resource (@allres) {
  736:         my $result = '';
  737:         my $applies = 0;
  738:         my $symb = $resource->symb();
  739:         %{$$bombed{$symb}} = ();
  740:         %{$$ungraded{$symb}} = ();
  741:         %{$$triggered{$symb}} = ();
  742:         $$triggered{$symb}{numparts} = 0;
  743:         if ($resource->encrypted()) {
  744:             $$triggered{$symb}{'enclink'} = $resource->link();
  745:             $$triggered{$symb}{'encsymb'} = $resource->shown_symb();
  746:         }
  747:         my $title = $resource->compTitle();
  748:         $$res_title{$symb} = $title;
  749:         my $ressymb = $resource->wrap_symb();
  750: 
  751: # Check if there are unread discussion postings
  752:         if ($$show{'coursediscussion'}) {
  753:             &check_discussions($resource,$symb,$ressymb,$title,
  754: 			       $newdiscussions,$unread,$countunread);
  755:         }
  756: 
  757: # Check for ungraded problems
  758:         if ($resource->is_problem()) {
  759:             if ($$show{'handgrading'}) {
  760:                 &check_handgraded($resource,$symb,$title,$cdom,$crs,$ungraded,
  761:                                                                      $tograde);
  762:             }
  763:         }
  764: 
  765: # Check for bombs
  766:         if ($$show{'haserrors'}) {
  767:             &check_bombed($resource,$symb,$title,$bombs,$bombed);
  768:         }
  769: 
  770: # Maxtries and degree of difficulty for problem parts, unless handgradeable
  771:         if ($$show{'abovethreshold'}) {  
  772:             &check_thresholds($resource,$symb,\%resourcetracker,
  773: 			      $triggered,$threshold,$warnings);
  774:         }
  775: 
  776:     }
  777: }
  778: 
  779: sub check_discussions {
  780:     my ($resource,$symb,$ressymb,$title,$newdiscussions,$unread,
  781: 	$countunread) = @_;
  782: 
  783:     if (!$resource->hasDiscussion()) { return; }
  784: 
  785:     %{$$unread{$ressymb}} = ();
  786:     $$unread{$ressymb}{'title'} = $title;
  787:     $$unread{$ressymb}{'symb'} = $symb;
  788:     if ($resource->encrypted()) {
  789:         $$unread{$ressymb}{'enclink'} = $resource->link();
  790:         $$unread{$ressymb}{'encsymb'} = $resource->shown_symb();
  791:     }
  792:     push(@{$newdiscussions}, $ressymb);
  793:     
  794:     $$unread{$ressymb}{'lastpost'} = $resource->last_post_time();
  795:     
  796:     if ($countunread eq 'on') {
  797: 	$$unread{$ressymb}{'unreadcount'} = 
  798:                             $resource->discussion_info('unread');
  799:     }
  800: }
  801: 
  802: sub check_handgraded {
  803:     my ($resource,$symb,$title,$cdom,$cnum,$ungraded,$tograde) = @_;
  804:     if ($resource->is_problem()) {
  805:         my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
  806:         my $partlist=$resource->parts();
  807:         my $handgradeable;
  808:         foreach my $part (@$partlist) {
  809:             if ($resource->handgrade($part) eq 'yes') {
  810:                 $handgradeable=1; last;
  811:             }
  812:         }
  813:         if ($handgradeable) {
  814:             my @ungraded = &Apache::bridgetask::get_queue_symb_status(
  815:                                              'gradingqueue',$symb,$cdom,$cnum);
  816:             if (@ungraded > 0) {
  817:                 $$ungraded{$symb}{count} = scalar(@ungraded);
  818:                 $$ungraded{$symb}{title} = $title;
  819:                 if ($resource->encrypted()) {
  820:                     $$ungraded{$symb}{'enclink'} = $resource->link();
  821:                     $$ungraded{$symb}{'encsymb'} = $resource->shown_symb();
  822:                 }
  823:                 push(@{$tograde},$symb);
  824:             }
  825:         }
  826:     }
  827: }
  828: 
  829: sub check_bombed {
  830:     my ($resource,$symb,$title,$bombs,$bombed) = @_;
  831:     if ($resource->getErrors()) {
  832:         my $errors = $resource->getErrors();
  833:         $errors =~ s/^,//;
  834:         my @bombs = split(/,/, $errors);
  835:         my $errorcount = scalar(@bombs);
  836:         my $errorlink = '<a href="/adm/email?display='.
  837:                         &escape($bombs[0]).'">'.
  838:                         $title.'</a>';
  839:         $$bombed{$symb}{errorcount} = $errorcount;
  840:         $$bombed{$symb}{errorlink} = $errorlink;
  841:         push(@{$bombs}, $symb);
  842:     }
  843: }
  844: 
  845: sub check_thresholds {
  846:     my ($resource,$symb,$resourcetracker,$triggered,$threshold,$warnings) = @_;
  847: # Compile maxtries and degree of difficulty for problem parts, unless handgradeable
  848:     my @parts = @{$resource->parts()};
  849:     my %stats;
  850:     my %lastreset = ();
  851:     my $warning = 0;
  852:     my $rowColor;
  853:     foreach my $part (@parts) {
  854:         if ($resource->handgrade($part) eq 'yes') {
  855:             next;
  856:         }
  857:         if ($resource->is_survey($part)) {
  858:             next;
  859:         }
  860:         %{$stats{$part}} = ();
  861:         my ($attempts,$users,$corrects,$degdiff,$av_attempts);
  862:         if (exists($$resourcetracker{$symb."\0".$part."\0attempts"})) {
  863:             $attempts = $$resourcetracker{$symb."\0".$part."\0attempts"};
  864:         }
  865:         if (exists($$resourcetracker{$symb."\0".$part."\0users"})) {
  866:             $users = $$resourcetracker{$symb."\0".$part."\0users"};
  867:         }
  868:         if (exists($$resourcetracker{$symb."\0".$part."\0correct"})) {
  869:             $corrects = $$resourcetracker{$symb."\0".$part."\0correct"};
  870:         }
  871:         if ($attempts > 0) {
  872:             $degdiff =  1 - ($corrects/$attempts);
  873:             $degdiff = sprintf("%.2f",$degdiff);
  874:         }
  875:         if ($users > 0) {
  876:             $av_attempts = $attempts/$users;
  877:             $av_attempts = sprintf("%.2f",$av_attempts);
  878:         }
  879:         if ((($degdiff ne '' && $degdiff >= $$threshold{'degdiff'}) || ($av_attempts ne '' && $av_attempts >= $$threshold{'av_attempts'})) && ($users >= $$threshold{'numstudents'})) {
  880:             $stats{$part}{degdiff} = $degdiff;
  881:             $stats{$part}{attempts} = $av_attempts;
  882:             $stats{$part}{users} = $users;
  883:             $lastreset{$part} = $$resourcetracker{$symb."\0".$part."\0resettime"};
  884:             if ($lastreset{$part}) {
  885:                 $lastreset{$part} = &Apache::lonnavmaps::timeToHumanString($lastreset{$part});
  886:             }
  887:             $warning = 1;
  888:         }
  889:     }
  890:     if ($warning) {
  891:         $$triggered{$symb}{title} = $resource->title;
  892:         my $partcount = 0;
  893:         @{$$triggered{$symb}{text}} = ();
  894:         foreach my $part (@parts) {
  895:             if (exists($stats{$part}{users})) {
  896:                 my $resetname = 'reset_'.&escape($symb."\0".$part);
  897:                 my $resettitle = 'title_'.&escape($symb."\0".$part);
  898:                 if (@parts > 1) {
  899:                     $$triggered{$symb}{text}[$partcount] = '
  900:                      <td>part - '.$part.'</td>';
  901:                 } else {
  902:                     $$triggered{$symb}{text}[$partcount] = '
  903:                      <td>single part</td>';
  904:                 }
  905:                 $$triggered{$symb}{text}[$partcount] .= '
  906:                      <td>'.$stats{$part}{users}.'</td>
  907:                      <td>'.$stats{$part}{attempts}.'</td>
  908:                      <td>'.$stats{$part}{degdiff}.'</td>
  909:                      <td>'.$lastreset{$part}.'</td>
  910:                      <td><input type="checkbox" name="'.$resetname.'" /><input type="hidden" name="'.$resettitle.'" value="'.&escape($$triggered{$symb}{title}).'" /></td>';
  911:                 $partcount ++;
  912:             }
  913:             $$triggered{$symb}{numparts} = $partcount;
  914:         }
  915:         push(@{$warnings},$symb);
  916:     }
  917: }
  918: 
  919: 
  920: sub get_curr_thresholds {
  921:     my ($threshold,$uname,$udom,$cid,$cdom,$crs) = @_;
  922:     # set default values
  923:     %$threshold = (av_attempts => 2,
  924:                   degdiff => 0.5,
  925:                   numstudents => 2
  926:                   );
  927:     my %thresholdsettings = &Apache::lonnet::dump('nohist_whatsnew',$udom,
  928:                                                      $uname,$cid.':threshold');
  929:     my $thresholdcount = 0;
  930:     my ($tmp) = %thresholdsettings;
  931:     unless ($tmp =~ /^(con_lost|error|no_such_host)/i) {
  932:         foreach my $item (keys %{$threshold}) { 
  933:             if (exists($thresholdsettings{$cid.':threshold_'.$item})) {
  934:                 $$threshold{$item} = 
  935:                              $thresholdsettings{$cid.':threshold_'.$item};
  936:                 $thresholdcount ++;
  937:             }
  938:         }
  939:     }
  940:     if ($thresholdcount == 3) {
  941:         return;
  942:     }
  943:     my %coursesettings = &Apache::lonnet::dump('environment',
  944:                                               $cdom,$crs,'internal.threshold');
  945:     my ($temp) = %coursesettings;
  946:     unless ($temp =~ /^(con_lost|error|no_such_host)/i) {  
  947:         foreach my $item (keys %{$threshold}) {
  948:             unless (exists($thresholdsettings{$cid.':threshold_'.$item})) {
  949:                 if (exists($coursesettings{'internal.threshold_'.$item})) {
  950:                     $$threshold{$item} = 
  951:                              $coursesettings{'internal.threshold_'.$item};
  952:                 }
  953:             }
  954:         }
  955:     }
  956:     return;
  957: }
  958: 
  959: sub get_current {
  960:     my ($uname,$udom,$cid,$caller) = @_;
  961:     my $currvalue;
  962:     my %settings = &Apache::lonnet::dump('nohist_whatsnew',$udom,$uname,$cid.
  963:                                                                 ':'.$caller);
  964:     my ($tmp) = %settings;
  965:     unless ($tmp =~ /^(con_lost|error|no_such_host)/i) {
  966:         $currvalue = $settings{$cid.':'.$caller};
  967:     }
  968:     return $currvalue;
  969: }
  970: 
  971: sub process_reset {
  972:     my ($dom,$crs) = @_;
  973:     my $result = '<b>'.&mt('Counters reset for following problems (and parts):').
  974:                            '</b><br />';
  975:     my @agg_types = ('attempts','users','correct');
  976:     my %agg_titles = &Apache::lonlocal::texthash (
  977:                      attempts => 'Number of submissions',
  978:                      users => 'Students with submissions',
  979:                      correct => 'Number of correct submissions',
  980:                      );
  981:     my @resets = ();
  982:     my %titles = ();
  983:     foreach my $key (keys(%env)) {
  984:         next if ($key !~ /^form\.reset_(.+)$/);
  985:         my $title = &unescape($env{'form.title_'.$1});
  986:         my $reset_item = &unescape($1);
  987:         my %curr_aggregates = &Apache::lonnet::dump('nohist_resourcetracker',$dom,$crs,$reset_item);
  988:         my %aggregates = ();
  989:         my ($symb,$part) = split(/\0/,$reset_item);
  990:         foreach my $type (@agg_types) {
  991:             $aggregates{$reset_item."\0".$type} = 0;
  992:         }  
  993: 	$aggregates{$reset_item."\0".'resettime'} = time;
  994:         my $putresult = &Apache::lonnet::put('nohist_resourcetracker',\%aggregates,
  995:                           $dom,$crs);
  996:         if ($putresult eq 'ok') {
  997:             $result .= $title.' -part '.$part.': ';
  998:             my %new_aggregates = &Apache::lonnet::dump('nohist_resourcetracker',$dom,$crs,$reset_item);
  999:             foreach my $type (@agg_types) {
 1000:                 $result .= $agg_titles{$type}.' = '.$new_aggregates{$reset_item."\0".$type}.'; ';
 1001:             }
 1002:             $result =~ s/; $//;
 1003:             $result .= '<br />';
 1004:         } else {
 1005:             $result = $title.' -part '.$part.': '.&mt('Unable to reset counters to zero due to [_1]',$putresult).'.<br />'."\n";
 1006:         }
 1007:     }
 1008:     return $result;
 1009: }
 1010: 
 1011: sub process_update {
 1012:     my ($uname,$udom,$threshold_titles) = @_;
 1013:     my $setoutput = '<b>Changes to threshold(s) for problem tracking:</b><br />';
 1014:     foreach (keys %env) {
 1015:         next if ($_!~/^form\.(.+)\_setparmval$/);
 1016:         my $name  = $1;
 1017:         my $value = $env{'form.'.$name.'_value'};
 1018:         if ($name && defined($value) && ($value ne '')) {
 1019:             my $put_result = &Apache::lonnet::put('nohist_whatsnew',
 1020:                                                   {$name=>$value},$udom,$uname);
 1021:            
 1022:             my ($shortname) = ($name =~ /^\Q$env{'request.course.id'}\E:threshold_(.+)$/);
 1023:             if ($put_result eq 'ok') {
 1024:                 $setoutput.=&mt('Set threshold for [_1] to [_2]',
 1025: 				'<b>'.$$threshold_titles{$shortname}.'</b>',
 1026: 				'<b>'.$value.'</b>').'<br />';
 1027: 	    } else {
 1028:                 $setoutput.=&mt('Unable to set threshold for [_1] to [_2] due to [_3].',
 1029: 				'<b>'.$name.'</b>','<b>'.$value.'</b>',
 1030: 				'<tt>'.$put_result.'</tt>').'<br />';
 1031:             }
 1032:         }
 1033:     }
 1034:     return $setoutput;
 1035: }
 1036: 
 1037: sub getnormalmail {
 1038:     my ($newmsgs) = @_;
 1039: # Check for unread mail in course
 1040:     my $msgcount = 0;
 1041: 
 1042:     my @messages = sort(&Apache::lonnet::getkeys('nohist_email'));
 1043:     foreach my $message (@messages) {
 1044: 	my $msgid=&escape($message);
 1045:         my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)=
 1046:             &Apache::lonmsg::unpackmsgid($msgid);
 1047:         if (($fromcid) && ($fromcid eq $env{'request.course.id'})) {
 1048:             if (defined($sendtime) && $sendtime!~/error/) {
 1049:                 my $numsendtime = $sendtime;
 1050:                 $sendtime = &Apache::lonlocal::locallocaltime($sendtime);
 1051:                 if ($status eq 'new') {
 1052:                     $msgcount ++;
 1053:                     if ($shortsubj eq '') {
 1054:                         $shortsubj = &mt('No subject');
 1055:                     }
 1056:                     push(@{$newmsgs}, {
 1057:                         msgid    => $msgid,
 1058:                         sendtime => $sendtime,
 1059:                         shortsub => $shortsubj,
 1060:                         from     => $fromname,
 1061:                         fromdom  => $fromdom
 1062:                         });
 1063:                 }
 1064:             }
 1065:         }
 1066:     }
 1067:     return $msgcount;
 1068: }
 1069: 
 1070: sub getcritmail {
 1071:     my ($critmsgs) = @_; 
 1072: # Check for critical messages in course
 1073:     my %what=&Apache::lonnet::dump('critical');
 1074:     my $result = '';
 1075:     my $critmsgcount = 0;
 1076:     foreach my $msgid (sort(keys(%what))) {
 1077:         my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)=
 1078:             &Apache::lonmsg::unpackmsgid($msgid);
 1079:         if (($fromcid) && ($fromcid eq  $env{'request.course.id'})) {
 1080:             if (defined($sendtime) && $sendtime!~/error/) {
 1081:                 my $numsendtime = $sendtime;
 1082:                 $sendtime = &Apache::lonlocal::locallocaltime($sendtime);
 1083:                 $critmsgcount ++;
 1084:                 if ($shortsubj eq '') {
 1085:                     $shortsubj = &mt('No subject');
 1086:                 }
 1087:                 push(@{$critmsgs}, {
 1088:                         msgid    => $msgid,
 1089:                         sendtime => $sendtime,
 1090:                         shortsub => $shortsubj,
 1091:                         from     => $fromname,
 1092:                         fromdom  => $fromdom
 1093:                         });
 1094:             }
 1095:         }
 1096:     }
 1097:     return $critmsgcount;
 1098: }
 1099: 
 1100: 
 1101: sub checkversions {
 1102:     my ($cdom,$crs,$navmap,$changed,$starttime) = @_;
 1103:     my %changes=&Apache::lonnet::dump('versionupdate',$cdom,$crs);
 1104:     my ($tmp) = keys(%changes);
 1105:     unless ($tmp =~ /^(con_lost|error|no_such_host)/i) {
 1106:         if (keys(%changes) > 0) {
 1107:             foreach my $key (sort(keys(%changes))) {
 1108:                 if ($changes{$key} > $starttime) {
 1109:                     my $version;
 1110:                     my ($root,$extension)=($key=~/^(.*)\.(\w+)$/);
 1111:                     my $currentversion=&Apache::lonnet::getversion($key);
 1112:                     my $revdate = 
 1113:                           &Apache::lonnet::metadata($root.'.'.$extension,
 1114:                                                      'lastrevisiondate');
 1115:                     $revdate =  &Apache::lonlocal::locallocaltime($revdate);
 1116:                     my $linkurl=&Apache::lonnet::clutter($key);
 1117:                     my $usedversion=$navmap->usedVersion('version_'.$linkurl);
 1118:                     my @resources = $navmap->getResourceByUrl($linkurl,1);
 1119:                     if (($usedversion) && ($usedversion ne 'mostrecent')) {
 1120:                         $version = $usedversion;     
 1121:                     } else {
 1122:                         $version = $currentversion;
 1123:                     }
 1124:                     foreach my $res (@resources) {
 1125:                          if (ref($res) eq 'Apache::lonnavmaps::resource') { 
 1126:                             my $symb = $res->symb();
 1127:                             %{$$changed{$symb}} = (
 1128:                                                 current => $currentversion,
 1129:                                                 version => $version,
 1130:                                                 revdate => $revdate,
 1131:                             );
 1132:                         }
 1133:                     }
 1134:                 }
 1135:             }
 1136:         }
 1137:     }
 1138:     return;
 1139: }
 1140: 
 1141: sub display_handgrade {
 1142:     my ($r,$tograde,$rowColor1,$rowColor2,$ungraded) = @_;
 1143:     my $rowColor;
 1144:     my %lt = &Apache::lonlocal::texthash(
 1145:                         'prna' => 'Problem Name',
 1146:                         'nmun' => 'Number ungraded',
 1147:                         'nopr' => 'No problems require handgrading',
 1148:     );
 1149:     if (@{$tograde} > 0) {
 1150:         $r->print('<tr bgcolor="#cccccc"><td><b><small>'.$lt{'prna'}.'</small></b></td><td align="right"><b><small>'.$lt{'nmun'}.'</small></b></td></tr>');
 1151:         my $rowNum = 0;
 1152:         foreach my $res (@{$tograde}) {
 1153:             if ($rowNum %2 == 1) {
 1154:                 $rowColor = $rowColor1;
 1155:             } else {
 1156:                 $rowColor = $rowColor2;
 1157:             }
 1158:             my ($map,$id,$url)=&Apache::lonnet::decode_symb($res);
 1159:             my $linkurl=&Apache::lonnet::clutter($url);
 1160:             $linkurl .= '?symb='.&escape($res);
 1161:             if ($$ungraded{$res}{'enclink'}) {
 1162:                 $linkurl = 
 1163:                     $$ungraded{$res}{'enclink'}.'?symb='.$$ungraded{$res}{'encsymb'};
 1164:             } 
 1165:             $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>');
 1166:             $rowNum ++;
 1167:         }
 1168:     } else {
 1169:         $r->print('<tr><td bgcolor="#ffffff"><br><center><i><b><small>&nbsp;&nbsp;'.$lt{'nopr'}.'&nbsp;&nbsp;</small><br><br></b></i></td></tr>');
 1170:     }
 1171: }
 1172: 
 1173: sub display_haserrors {
 1174:     my ($r,$bombs,$rowColor1,$rowColor2,$bombed,$res_title) = @_;
 1175:     my $bombnum = 0;
 1176:     my $rowColor;
 1177:     my %lt = &Apache::lonlocal::texthash(
 1178:                                    reso => 'Resource',
 1179:                                    nmer => 'Number of errors',
 1180:                                    noer => 'No problems with errors',
 1181:     );
 1182:     if (@{$bombs} > 0) {
 1183:         $r->print('<tr bgcolor="#cccccc"><td><b><small>'.$lt{'reso'}.'</small></b></td><td align="right"><b><small>'.$lt{'nmer'}.'</small></b></td></tr>');
 1184:         @{$bombs} = sort { &cmp_title($a,$b,$res_title) } @{$bombs};
 1185:         foreach my $bomb (@{$bombs}) {
 1186:             if ($bombnum %2 == 1) {
 1187:                 $rowColor = $rowColor1;
 1188:             } else {
 1189:                 $rowColor = $rowColor2;
 1190:             }
 1191:             $r->print('<tr bgcolor="'.$rowColor.'"><td><small>'.$$bombed{$bomb}{errorlink}.'</small></td><td align="right"><small>'.$$bombed{$bomb}{errorcount}.'</small></td></tr>');
 1192:             $bombnum ++;
 1193:         }
 1194:     } else {
 1195:         $r->print('<tr><td bgcolor="#ffffff"><br /><center><b><i><small>'.$lt{'noer'}.'</small></i></b></center><br /></td></tr>');
 1196:     }
 1197:     return;
 1198: }
 1199: 
 1200: sub display_abovethreshold {
 1201:     my ($r,$refpage,$warnings,$triggered,$res_title) = @_;
 1202:     my %lt = &Apache::lonlocal::texthash(
 1203:                  reso => 'Resource',
 1204:                  part => 'Part',
 1205:                  nust => 'Num. students',
 1206:                  avat => 'Av. Attempts',
 1207:                  dedi => 'Deg. Diff',
 1208:                  lare => 'Last Reset',
 1209:                  reco => 'Reset Count?',
 1210:                  rese => 'Reset counters to 0',
 1211:                  nopr => 'No problems satisfy threshold criteria',
 1212:     );
 1213:     if (@{$warnings} > 0) {
 1214:         @{$warnings} = sort { &cmp_title($a,$b,$res_title) } @{$warnings};
 1215:         $r->print('<form name="reset_tracking" method="post" action="/adm/whatsnew">'.
 1216:                 ' <input type="hidden" name="command" value="reset" />'."\n".
 1217:                 ' <input type="hidden" name="refpage" value="'.$refpage.'" />'.
 1218:                 "\n");
 1219:         $r->print('<tr class="LC_info_row">'.
 1220: 		  '<td class="LC_first_item">'.$lt{'reso'}.'</td>'.
 1221: 		  '<td>'.$lt{'part'}.'</td><td>'.$lt{'nust'}.'</td>'.
 1222: 		  '<td>'.$lt{'avat'}.'</td><td>'.$lt{'dedi'}.'</td>'.
 1223: 		  '<td>'.$lt{'lare'}.'</td><td>'.$lt{'reco'}.'</td></tr>');
 1224: 	my $row;
 1225:         foreach my $res (@{$warnings}) {
 1226: 	    $row++;
 1227:             my ($map,$id,$url)=&Apache::lonnet::decode_symb($res);
 1228:             my $linkurl=&Apache::lonnet::clutter($url);
 1229:             my $rowspan;
 1230:             if ($$triggered{$res}{numparts} > 1) {
 1231:                 $rowspan = 'rowspan="'.$$triggered{$res}{numparts}.'"';
 1232:             }
 1233:             $linkurl .= '?symb='.&escape($res);
 1234:             if ($$triggered{$res}{'enclink'}) {
 1235:                 $linkurl = 
 1236:                   $$triggered{$res}{'enclink'}.'?symb='.$$triggered{$res}{'encsymb'};
 1237:             }
 1238:             my $css_class = $row%2?'LC_odd_row':'';
 1239:             $r->print('<tr class="'.$css_class.'">'.
 1240: 		      '<td class="LC_first_item" '.$rowspan.'><a href="'.$linkurl.'">'.
 1241: 		      $$triggered{$res}{title}.'</a></td>');
 1242:                       if (ref($$triggered{$res}{text}) eq 'ARRAY') {
 1243: 		          $r->print($$triggered{$res}{text}[0]);
 1244:                       }
 1245:                       $r->print('</tr>');
 1246:             if (ref($$triggered{$res}{text}) eq 'ARRAY') {
 1247:                 if (@{$$triggered{$res}{text}} > 1) {
 1248:                     for (my $i=1; $i<@{$$triggered{$res}{text}}; $i++) {
 1249:                         $r->print('<tr class="'.$css_class.'">'.
 1250:                                   $$triggered{$res}{text}[$i].'</tr>');
 1251:                     }
 1252:                 }
 1253:             }
 1254:         }
 1255:         $r->print('<tr class="LC_info_row"><td colspan="7"><br /><input type="submit" name="counters" value="'.$lt{'rese'}.'" /></td></tr></form>');
 1256:     } else {
 1257:         $r->print('<tr class="LC_empty_row"><td>'.$lt{'nopr'}.'</td></tr>');
 1258:     }
 1259: }
 1260: 
 1261: sub display_versionchanges {
 1262:     my ($r,$changed,$res_title,$rowColor1,$rowColor2,$interval) = @_;
 1263:     my %lt = &Apache::lonlocal::texthash(
 1264:         'reso' => 'Resource',
 1265:         'revd' => 'Last revised',
 1266:         'newv' => 'New version',
 1267:         'veru' => 'Version used',
 1268:         'noup' => 'No updated versions', 
 1269:     );
 1270:     my $rowColor;
 1271:     if (keys(%{$changed}) > 0) {
 1272:         $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>');
 1273:         
 1274:         
 1275:         my @changes = sort { &cmp_title($a,$b,$res_title) } keys(%{$changed});
 1276:         my $changenum = 0;
 1277:         foreach my $item (@changes) {
 1278:             if ($changenum %2 == 1) {
 1279:                 $rowColor = $rowColor1;
 1280:             } else {
 1281:                 $rowColor = $rowColor2;
 1282:             }
 1283:             my ($map,$id,$url)=&Apache::lonnet::decode_symb($item);
 1284:             my $linkurl=&Apache::lonnet::clutter($url);
 1285:             $linkurl .= '?symb='.&escape($item);
 1286: 
 1287:             $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>');
 1288:             $changenum ++;
 1289:         }
 1290:     } else {
 1291:         $r->print('<tr><td bgcolor="#ffffff"><br /><center><b><i><small>'.$lt{'noup'}.' '.$interval.'</small></i></b></center><br /></td></tr>');
 1292:     }
 1293:     return;
 1294: }
 1295:  
 1296: sub display_coursediscussion {
 1297:     my ($r,$newdiscussions,$unread,$countunread,$res_title,$rowColor1,
 1298:                                                               $rowColor2) = @_;
 1299:     my $lctype = lc(&Apache::loncommon::course_type());
 1300:     my %lt = &Apache::lonlocal::texthash(
 1301:                 'loca' => 'Location',
 1302:                 'type' => 'Type',
 1303:                 'numn' => 'Number of new posts',
 1304:                 'noun' => 'No unread posts in '.$lctype.' discussions',
 1305:                 'tmlp' => 'Time of last post', 
 1306:     );
 1307:     my $rowColor;
 1308:     if (@{$newdiscussions} > 0) {
 1309:         $r->print('<tr bgcolor="#cccccc"><td><b><small>'.$lt{'loca'}.
 1310:                   '</small></b></td><td><b><small>'.$lt{'type'}.
 1311:                   '</small></b>');
 1312:         if ($countunread eq 'on') {
 1313:             $r->print('<td><b><small>'.$lt{'tmlp'}.'</small></b></td>'.
 1314:                       '<td align="right"><b><small>'.$lt{'numn'}.
 1315:                       '</small></b></td>');
 1316:         } else {
 1317:             $r->print('<td align="right"><b><small>'.$lt{'tmlp'}.
 1318:                          '</small></b></td>');
 1319:         }
 1320:         $r->print("</tr>\n");
 1321:         @{$newdiscussions} = sort { &cmp_title($a,$b,$res_title) }
 1322:                                                             @{$newdiscussions};
 1323:         my $rowNum = 0;
 1324:         foreach my $ressymb (@{$newdiscussions}) {
 1325:             my $forum_title = $$unread{$ressymb}{'title'};
 1326:             my $type = 'Resource';
 1327:             my $feedurl=&Apache::lonfeedback::get_feedurl($ressymb);
 1328:             my $disclink = $feedurl.'?symb='.$$unread{$ressymb}{symb};
 1329:             if ($feedurl =~ /bulletinboard/) {
 1330:                 $type = 'Bulletin Board';
 1331:             }
 1332:             if ($$unread{$ressymb}{'enclink'}) {
 1333:                 $disclink = $$unread{$ressymb}{'enclink'}.'?symb='.$$unread{$ressymb}{'encsymb'};
 1334:             }
 1335:             if ($rowNum %2 == 1) {
 1336:                 $rowColor = $rowColor1;
 1337:             } else {
 1338:                 $rowColor = $rowColor2;
 1339:             }
 1340:             my $lastpost = &Apache::lonnavmaps::timeToHumanString(
 1341:                                                $$unread{$ressymb}{'lastpost'});
 1342:             $r->print('<tr bgcolor="'.$rowColor.'"><td><small><a href="'.$disclink.'">'.$forum_title.'</a>&nbsp;</td><td><small>'.$type.'&nbsp;</small></td>');
 1343:             if ($countunread eq 'on') {
 1344:                 my $unreadnum = $$unread{$ressymb}{'unreadcount'};
 1345:                 $r->print('<td><small>'.$lastpost.'<small></td><td align="right">'.
 1346:                           '<small>',$unreadnum.'&nbsp;</small></td>');
 1347:             } else {
 1348:                 $r->print('<td align="right"><small>'.$lastpost.'</small></td>');
 1349:             }
 1350:             $r->print("</tr>\n");
 1351:             $rowNum ++;
 1352:         }
 1353:     } else {
 1354:         $r->print('<tr><td bgcolor="#ffffff"><br><center>&nbsp;<i><b><small>'.
 1355:                   $lt{'noun'}.'</small></b></i><br><br></td></tr>');
 1356:     }
 1357: }
 1358: 
 1359: sub display_coursenormalmail {
 1360:     my ($r,$msgcount,$newmsgs,$rowColor1,$rowColor2) = @_;
 1361:     my $rowColor;
 1362:     my $lctype = lc(&Apache::loncommon::course_type());
 1363:     if ($msgcount > 0) {
 1364:         $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>');
 1365:         my $rowNum = 0;
 1366:         my $mailcount = 1;
 1367:         foreach my $msg (@{$newmsgs}) {
 1368:             if ($rowNum %2 == 1) {
 1369:                 $rowColor = $rowColor1;
 1370:             } else {
 1371:                 $rowColor = $rowColor2;
 1372:             }
 1373:             $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>');
 1374:             $rowNum ++;
 1375:             $mailcount ++;
 1376:         }
 1377:     } else {
 1378:         $r->print('<tr><td bgcolor="#ffffff" width="100%"><center><br /><b><i><small>'.&mt('No new '.$lctype.' messages').'</small></i></b><br /><br /></center></td></tr>');
 1379:     }
 1380: }
 1381: 
 1382: sub display_coursecritmail {
 1383:     my ($r,$critmsgcount,$critmsgs,$rowColor1,$rowColor2) = @_;
 1384:     my $rowColor;
 1385:     my $lctype = lc(&Apache::loncommon::course_type());
 1386:     if ($critmsgcount > 0) {
 1387:         $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>');
 1388:         my $rowNum = 0;
 1389:         my $mailcount = 1;
 1390:         foreach my $msg (@{$critmsgs}) {
 1391:             if ($rowNum %2 == 1) {
 1392:                 $rowColor = $rowColor1;
 1393:             } else {
 1394:                 $rowColor = $rowColor2;
 1395:             }
 1396:             $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>');
 1397:             $rowNum ++;
 1398:             $mailcount ++;
 1399:         }
 1400:     } else {
 1401:         $r->print('<tr><td bgcolor="#ffffff" width="100%"><center><br /><b><i><small>'.&mt('No unread critical messages in '.$lctype).'</small></i></b><br /><br /></center></td></tr>');
 1402:     }
 1403: }
 1404: 
 1405: sub cmp_title {
 1406:     my ($a,$b,$res_title) = @_;
 1407:     my ($atitle,$btitle) = (lc($$res_title{$a}),lc($$res_title{$b}));
 1408:     $atitle=~s/^\s*//;
 1409:     $btitle=~s/^\s*//;
 1410:     return $atitle cmp $btitle;
 1411: }
 1412: 
 1413: sub get_display_settings {
 1414:     my ($uname,$udom,$cid) = @_;
 1415:     my %settings = &Apache::lonnet::dump('nohist_whatsnew',$udom,$uname,$cid); 
 1416:     my ($tmp) = keys(%settings);
 1417:     if ($tmp=~ /^(con_lost|error|no_such_host)/i) {
 1418:         %settings = ();
 1419:         unless ($tmp =~ /^error: 2 /) {
 1420: 	    my $lctype = lc(&Apache::loncommon::course_type());
 1421:             &Apache::lonnet::logthis('Error retrieving whatsnew settings: '.
 1422:             $tmp.' for '.$uname.':'.$udom.' for '.$lctype.': '.$cid);
 1423:         }
 1424:     }
 1425:     return %settings;
 1426: }
 1427: 
 1428: sub store_display_settings {
 1429:     my ($uname,$udom,$cid,$checkallowed) = @_;
 1430:     my %whatsnew_settings;
 1431:     my $result;
 1432:     foreach my $key (keys(%{$checkallowed})) {
 1433: 	if ($key =~ /_section$/) { next; }
 1434:         if (exists($env{'form.display_'.$key})) {
 1435:             unless ($env{'form.display_'.$key} eq '') {
 1436:                 $whatsnew_settings{$cid.':'.$key} = $env{'form.display_'.$key};
 1437:             }
 1438:         }
 1439:     }
 1440:     if (keys(%whatsnew_settings)) {
 1441:         $result = &Apache::lonnet::put('nohist_whatsnew',\%whatsnew_settings,
 1442:                                                                  $udom,$uname);
 1443:     } else {
 1444:         $result = 'ok';
 1445:     }
 1446:     return $result;
 1447: }
 1448: 
 1449: sub store_interval_setting {
 1450:     my ($uname,$udom,$cid,$interval_titles) = @_;
 1451:     my %interval_settings = ();
 1452:     my $result;
 1453:     if (defined($env{'form.interval'})) {
 1454:         $interval_settings{$cid.':interval'} = $env{'form.interval'};
 1455:         my $outcome = &Apache::lonnet::put('nohist_whatsnew',
 1456:                                              \%interval_settings,$udom,$uname);
 1457:         if ($outcome eq 'ok') {
 1458:             $result = &mt('Interval set to version changes [_1]',
 1459:                   '<b>'.$$interval_titles{$env{'form.interval'}}.'</b><br />');
 1460: 
 1461:         } else {
 1462: 	    my $lctype = lc(&Apache::loncommon::course_type());
 1463:             &Apache::lonnet::logthis('Error storing whatsnew interval setting'.
 1464:                 ' '.$outcome.' for '.$uname.':'.$udom.' in '.$lctype.' '.$cid);
 1465:             $result = &mt('Unable to set interval to [_1] due to [_2].',
 1466:                          '<b>'.$$interval_titles{$env{'form.interval'}}.'</b>',
 1467:                          '<tt>'.$outcome.'</tt>.<br />');
 1468:         }
 1469:     }
 1470:     return $result;
 1471: }
 1472: 
 1473: sub store_discussion_setting {
 1474:     my ($uname,$udom,$cid) = @_;
 1475:     my %discussion_settings;
 1476:     my $result;
 1477:     if (defined($env{'form.countunread'})) {
 1478:         $discussion_settings{$cid.':countunread'} = $env{'form.countunread'};
 1479:         my $outcome = &Apache::lonnet::put('nohist_whatsnew',
 1480:                                              \%discussion_settings,$udom,$uname);
 1481:         if ($outcome eq 'ok') {
 1482:             $result = &mt('Count unread posts in discussions display set to [_1]',
 1483:                   '<b>'.$env{'form.countunread'}.'</b><br />');
 1484:                                                                                   
 1485:         } else {
 1486: 	    my $lctype = lc(&Apache::loncommon::course_type());
 1487:             &Apache::lonnet::logthis('Error storing whatsnew countunread setting'.
 1488:                 ' '.$outcome.' for '.$uname.':'.$udom.' in '.$lctype.' '.$cid);
 1489:             $result = &mt('Unable to set "number unread posts display" to [_1]'.
 1490:                           ' due to [_2].',
 1491:                          '<b>'.$env{'form.countunread'}.'</b>',
 1492:                          '<tt>'.$outcome.'</tt>.<br />');
 1493:         }
 1494:     }
 1495:     return $result;
 1496: }
 1497: 
 1498: sub store_courseinit_setting {
 1499:     my ($uname,$udom,$cid,$initpage) = @_;
 1500:     my %courseinit_settings;
 1501:     my $page_control;
 1502:     my $result;
 1503:     if (defined($env{'form.courseinit_control'})) {
 1504:         if ($env{'form.courseinit_control'} eq 'userpref') {
 1505:             $courseinit_settings{$cid.':courseinit'} = '';
 1506:             $page_control = 'global preferences';
 1507:         } else {
 1508:             if (defined($env{'form.courseinit_page'})) {
 1509:                 $courseinit_settings{$cid.':courseinit'} = 
 1510:                                                   $env{'form.courseinit_page'};
 1511:                 $page_control = 'course specific setting';
 1512:             }
 1513:         }
 1514:         if ($page_control) {
 1515: 	    my $lctype = lc(&Apache::loncommon::course_type());
 1516:             my $outcome = &Apache::lonnet::put('nohist_whatsnew',
 1517:                                            \%courseinit_settings,$udom,$uname);
 1518:             if ($outcome eq 'ok') {
 1519:                 if ($page_control eq 'global preferences') {
 1520:                     $result = &mt("Page displayed after role selection in $lctype now set by <b>user's global preferences</b>.");
 1521:                 } else {
 1522:                     $result = &mt('Page displayed after role selection in this '.$lctype.' set to <b>[_2]</b>',$lctype,$$initpage{$env{'form.courseinit_page'}});
 1523:                 }
 1524:             } else {
 1525:                 &Apache::lonnet::logthis('Error storing whatsnew courseinit '.
 1526:                                          'setting: '.$outcome.' for '.$uname.
 1527:                                          ':'.$udom.' in '.$lctype.' '.$cid);
 1528:                 if ($page_control eq 'global preferences') {
 1529:                     $result = &mt('Unable to set control of page display to [_1]'.
 1530:                           ' due to [_2].',
 1531:                          '<b>'.$page_control.'</b>',
 1532:                          '<tt>'.$outcome.'</tt>.<br />');
 1533:                 } else {
 1534:                     $result = &mt('Unable to set page display, after role selection, for this '.$lctype.' to <b>[_2]</b> due to <tt>[_3]</tt>.<br />',
 1535:                          $$initpage{$env{'form.courseinit_page'}},$outcome);
 1536:                 }
 1537:             }
 1538:         }
 1539:     }
 1540:     return $result;
 1541: }
 1542: 
 1543: sub start_box {
 1544:     my ($r,$tabbg,$show,$heading,$caller,$refpage) = @_;
 1545:     my %lt = &Apache::lonlocal::texthash( 
 1546:                        chth => 'Change thresholds?',
 1547:                        chin => 'Change interval?',
 1548:                        chop => 'Change options?',
 1549:     );
 1550:     my ($showhide,$class);
 1551:     if ($$show{$caller}) {
 1552:         $showhide = '<b><a href="javascript:change_display(document.visible.'.
 1553:                                'display_'.$caller.",'hide'".');">Hide</a></b>';
 1554:    
 1555:     } else {
 1556:         $showhide = '<b><a href="javascript:change_display(document.visible.'.
 1557:                                'display_'.$caller.",'show'".');">Show</a></b>';
 1558:     }
 1559:     
 1560:     $r->print('
 1561:          <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000" width="100%">
 1562:           <tr>
 1563:            <td>
 1564:             <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000" width="100%">
 1565:               <tr>
 1566:                <td bgcolor="'.$tabbg.'">
 1567:                 <table width="100%" border="0" cellspacing="0" cellpadding="0">
 1568:                  <tr>
 1569:                   <td><b>'.$$heading{$caller}.'</b></td>
 1570:                   <td valign="top" align="right">'.$showhide.'</td>
 1571:                  </tr>
 1572:                 </table>
 1573:                </td>
 1574:               </tr>');
 1575:      if (($caller eq 'abovethreshold') && ($$show{$caller})) {
 1576:          if ($$show{$caller}) {
 1577:              $r->print('
 1578:               <tr>
 1579:                 <td bgcolor="'.$tabbg.'" align="right"><a href="/adm/whatsnew?command=chgthreshold&refpage='.$refpage.'"><b><small>'.$lt{'chth'}.'</small></b></a></td>
 1580:               </tr>');
 1581:          }
 1582: 	 $class='class="LC_whatsnew"';
 1583:      } elsif (($caller eq 'versionchanges') && ($$show{$caller})) {
 1584:          if ($$show{$caller}) {
 1585:              $r->print('
 1586:               <tr>
 1587:                 <td bgcolor="'.$tabbg.'" align="right"><a href="/adm/whatsnew?command=chginterval&refpage='.$refpage.'"><b><small>'.$lt{'chin'}.'</small></b></a></td>
 1588:               </tr>');
 1589:          }
 1590:      } elsif ($caller eq 'coursediscussion') {
 1591:          if ($$show{$caller}) {
 1592:              $r->print('
 1593:               <tr>
 1594:                 <td bgcolor="'.$tabbg.'" align="right"><a href="/adm/whatsnew?command=chgdisc&refpage='.$refpage.'"><b><small>'.$lt{'chop'}.'</small></b></a></td>
 1595:               </tr>');
 1596:          }
 1597:      }
 1598:     $r->print('
 1599:               <tr>
 1600:                <td bgcolor="#ffffff">
 1601:                 <table cellpadding="2" cellspacing="0" border="0" width="100%" '.$class.'>
 1602: ');
 1603:     return;
 1604: }
 1605: 
 1606: sub end_box {
 1607:     my ($r) = shift;
 1608:     $r->print('
 1609:       </table>
 1610:      </td>
 1611:     </tr>
 1612:    </table>
 1613:   </td>
 1614:  </tr>
 1615: </table><br />');
 1616:     return;
 1617: }
 1618: 
 1619: 1;

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