--- loncom/interface/lonwhatsnew.pm 2005/12/05 19:27:53 1.35 +++ loncom/interface/lonwhatsnew.pm 2005/12/20 15:56:38 1.40 @@ -1,5 +1,5 @@ # -# $Id: lonwhatsnew.pm,v 1.35 2005/12/05 19:27:53 raeburn Exp $ +# $Id: lonwhatsnew.pm,v 1.40 2005/12/20 15:56:38 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -52,41 +52,68 @@ sub handler { $r->send_http_header; return OK; } - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['command']); + &Apache::loncommon::get_unprocessed_cgi( + $ENV{'QUERY_STRING'},['command','refpage']); - my $command; - if ($env{'form.action'} eq 'reset') { - $command = 'reset'; - } elsif ($env{'form.action'} eq 'update') { - $command = 'update'; - } else { - $command = $env{'form.command'}; - } + my $command = $env{'form.command'}; + my $refpage = $env{'form.refpage'}; &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; - $r->print(&display_header($command)); - if (! (($env{'request.course.fn'}) && (&Apache::lonnet::allowed('bre',$env{'request.course.id'})))) { - # Not in a course, or not allowed to view action items - $env{'user.error.msg'}="/adm/whatsnew:bre:0:0:Cannot display what's new screen"; + 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=threshold', + ({href=>'/adm/whatsnew?command=chgthreshold&refpage='.$refpage, text=>"Change thresholds"}); $r->print(&Apache::lonhtmlcommon::breadcrumbs - (undef,'Course Action Items','Course_Action_Items_Thresholds')); - } else { + (undef,"What's New?",'Course_Action_Items_Thresholds')); + } elsif (($command eq 'chginterval') && (&Apache::lonnet::allowed('vgr',$env{'request.course.id'}))) { &Apache::lonhtmlcommon::add_breadcrumb - ({href=>'/adm/whatsnew', - text=>"Display Action Items"}); + ({href=>'/adm/whatsnew?command=chginterval&refpage='.$refpage, + text=>"Change interval"}); + $r->print(&Apache::lonhtmlcommon::breadcrumbs + (undef,"What's New?",'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,"What's New?",'Course_Action_Items_Intervals')); + } elsif ($command eq 'courseinit') { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/whatsnew?command=courseinit&refpage='.$refpage, + text=>"Course initialization preference"}); $r->print(&Apache::lonhtmlcommon::breadcrumbs - (undef,'Course Action Items','Course_Action_Items_Display')); + (undef,"What's New?",'Course_Action_Items_Initialization')); + } else { + $r->print(&Apache::lonhtmlcommon::breadcrumbs + (undef,"What's New?",'Course_Action_Items_Display')); } - &display_main_box($r,$command); + &display_main_box($r,$command,$refpage,\%checkallowed); return OK; } @@ -97,23 +124,49 @@ sub handler { #------------------------------ sub display_main_box { - my ($r,$command) = @_; + my ($r,$command,$refpage,$checkallowed) = @_; my $domain=&Apache::loncommon::determinedomain(); - my $tabbg=&Apache::loncommon::designparm('coordinator.tabbg',$domain); + my $function = &Apache::loncommon::get_users_function(); + my $tabbg=&Apache::loncommon::designparm($function.'.tabbg',$domain); $r->print('
'); - my %threshold_titles = ( + 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_config_box($r,$command,$tabbg,\%threshold_titles,$cdom,$crs); + 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,\%threshold_titles,$cdom,$crs); + &display_actions_box($r,$tabbg,$command,$refpage,\%threshold_titles, + \%interval_titles,\%initpage,$cdom,$crs,$checkallowed); } $r->print(< @@ -131,13 +184,37 @@ END_OF_BLOCK # up the HTML #------------------------------- -sub display_header{ +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"; + +'; + } return(< Course Action Items +$scripttag $bodytag ENDHEAD @@ -150,12 +227,24 @@ ENDHEAD # #------------------------------- -sub display_actions_box() { - my ($r,$command,$threshold_titles,$cdom,$crs) = @_; - +sub display_actions_box { + my ($r,$tabbg,$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 = (); @@ -175,13 +264,9 @@ sub display_actions_box() { 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 = ( @@ -189,61 +274,98 @@ sub display_actions_box() { 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 $pgbg=&Apache::loncommon::designparm($function.'.pgbg',$domain); - my $tabbg=&Apache::loncommon::designparm($function.'.tabbg',$domain); + my ($initcontrol,$initdisp) = &curr_courseinit(); + my $currinit = $pagedesc{$initdisp}.' ('.$pagedesc{$initcontrol}.')'; - unless ($env{'request.course.id'}) { - $r->print('
You are accessing an invalid course.


'); + unless ($cid) { + $r->print('
'.$lt{'yacc'}.'


'); return; } - my %checkallowed = ( - coursediscussion => &Apache::lonnet::allowed('pch',$env{'request.course.id'}), - handgrading => &Apache::lonnet::allowed('mgr',$env{'request.course.id'}), - abovethreshold => &Apache::lonnet::allowed('vgr',$env{'request.course.id'}), - haserrors => &Apache::lonnet::allowed('opa',$env{'request.course.id'}), - versionchanges => &Apache::lonnet::allowed('opa',$env{'request.course.id'}), - coursenormalmail => 1, - coursecritmail => 1, - ); + 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(''.$lt{'gtfr'}. + '
'); + } + } + $r->print($lt{'pgse'}.' '.&mt('Currently: [_1]',''.$currinit.''). + '  '.&mt('[_1] for just [_2]','Change', + 'this course').' '.&mt('or for all [_1].', + 'your courses').'

'); + + 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); + } - my $timediff = 604800; - my %display_settings = &get_display_settings(); + if ($result) { + $r->print($result.'
'); + } + $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 %intervals = ( - -1 => 'since start of course', - 2592000 => 'since last month', - 604800 => 'since last week', - 86400 => 'since yesterday', - ); - my $interval = $intervals{$timediff}; + 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 message', + coursenormalmail => 'New course messages', coursecritmail => 'New critical messages in course', ); - if ($checkallowed{'abovethreshold'}) { - &get_curr_thresholds(\%threshold,$cdom,$crs); + if ($$checkallowed{'abovethreshold'}) { + &get_curr_thresholds(\%threshold,$uname,$udom,$cid,$cdom,$crs); } $headings{'abovethreshold'} = &mt('Problems with av. attempts').' ≥ '.$threshold{'av_attempts'}.' '.&mt('or deg. difficulty').' ≥ '.$threshold{'degdiff'}.'
'.&mt('and total number of students with submissions').' ≥ '.$threshold{'numstudents'}; my @actionorder = ('handgrading','haserrors','abovethreshold','versionchanges','coursediscussion','coursenormalmail','coursecritmail'); - foreach my $key (keys(%checkallowed)) { + foreach my $key (keys(%{$checkallowed})) { $show{$key} = 0; - if ($checkallowed{$key}) { - unless ($display_settings{$key} eq 'off') { + if ($$checkallowed{$key}) { + unless ($display_settings{$cid.':'.$key} eq 'hide') { $show{$key} = 1; } } @@ -258,28 +380,8 @@ sub display_actions_box() { } } - - if (tie(my %bighash,'GDBM_File',$env{'request.course.fn'}.'.db', - &GDBM_READER(),0640)) { - my $furl=$bighash{'first_url'}; - $r->print('Go to first resource
Change your preferences
to suppress display of this screen when accessing courses as Course Coordinator in the future.

'); - untie(%bighash); - } - - my $result; - - if ($command eq 'reset') { - $result = &process_reset($cdom,$crs); - } elsif ($command eq 'update') { - $result = &process_update($cdom,$crs,$threshold_titles); - } - if ($result) { - $r->print($result.'
'); - } - $r->rflush(); - if ($needitems) { - &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\%changed,\@newdiscussions,\@tograde,\@bombs,\@warnings,$rowColor1,$rowColor2,\%threshold,$cdom,$crs,\%res_title,\%show,$starttime); + &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); @@ -288,19 +390,31 @@ sub display_actions_box() { &getcritmail(\@critmsgs); } - $r->print(qq|Hide All  Show All|); + $r->print(qq|$lt{'hial'} +   $lt{'shal'} +
\n|); + foreach my $item (keys(%{$checkallowed})) { + if ($$checkallowed{$item}) { + $r->print(''."\n"); + } + } - $r->print('
'); + $r->print('
'); foreach my $res (@{$warnings}) { if ($warningnum %2 == 1) { @@ -961,19 +1286,29 @@ sub display_versionchanges { } sub display_coursediscussion { - my ($r,$newdiscussions,$unread,$res_title,$rowColor1,$rowColor2) = @_; + 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(''); + ''); + if ($countunread eq 'on') { + $r->print(''. + ''); + } else { + $r->print(''); + } + $r->print("\n"); @{$newdiscussions} = sort { &cmp_title($a,$b,$res_title) } @{$newdiscussions}; my $rowNum = 0; @@ -984,17 +1319,23 @@ sub display_coursediscussion { if ($feedurl =~ /bulletinboard/) { $type = 'Bulletin Board'; } - my $unreadnum = keys(%{$$unread{$ressymb}}); - $unreadnum = $unreadnum - 2; - if ($unreadnum > 0) { - if ($rowNum %2 == 1) { - $rowColor = $rowColor1; - } else { - $rowColor = $rowColor2; - } - $r->print(''); - $rowNum ++; + if ($rowNum %2 == 1) { + $rowColor = $rowColor1; + } else { + $rowColor = $rowColor2; + } + my $lastpost = &Apache::lonnavmaps::timeToHumanString( + $$unread{$ressymb}{'lastpost'}); + $r->print(''); + if ($countunread eq 'on') { + my $unreadnum = $$unread{$ressymb}{'unreadcount'}; + $r->print(''); + } else { + $r->print(''); } + $r->print("\n"); + $rowNum ++; } } else { $r->print(''); if (($caller eq 'abovethreshold') && ($$show{$caller})) { - $r->print(' + if ($$show{$caller}) { + $r->print(' - + '); + } } elsif (($caller eq 'versionchanges') && ($$show{$caller})) { - $r->print(' + if ($$show{$caller}) { + $r->print(' + + + '); + } + } elsif ($caller eq 'coursediscussion') { + if ($$show{$caller}) { + $r->print(' - + '); + } } $r->print('
'); my $displayed = 0; - my $totalboxes = keys(%checkallowed); + my $totalboxes = 0; + foreach my $key (keys(%{$checkallowed})) { + if ($$checkallowed{$key}) { + $totalboxes ++; + } + } my $halfway = int($totalboxes/2) + $totalboxes%2; foreach my $actionitem (@actionorder) { - if ($checkallowed{$actionitem}) { + if ($$checkallowed{$actionitem}) { if ($displayed == $halfway) { - $r->print(' '); + $r->print(' '); } - &display_launcher($r,$actionitem,\%checkallowed,$tabbg,$rowColor1,$rowColor2,\%show,\%headings,\%res_title,\@tograde,\%ungraded,\@bombs,\%bombed,\%changed,\@warnings,\%triggered,\@newdiscussions,\%unread,$msgcount,\@newmsgs,$critmsgcount,\@critmsgs,$interval); + &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 ++; } } @@ -315,28 +429,37 @@ sub display_actions_box() { } #------------------------------- -# display_config_box +# display_threshold_config # # Display the threshold setting screen # #------------------------------- -sub display_config_box() { - my ($r,$command,$tabbg,$threshold_titles,$cdom,$crs) = @_; +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"); - my %threshold_titles = ( + 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,$cdom,$crs); + &get_curr_thresholds(\%threshold,$uname,$udom,$cid,$cdom,$crs); - $r->print('
+ $r->print('
+ + +
'); my $rowNum =0; foreach my $type (@thresholditems) { - my $parameter = 'internal.threshold_'.$type; + my $parameter = $env{'request.course.id'}.':threshold_'.$type; # onchange is javascript to automatically check the 'Set' button. my $onchange = 'onFocus="javascript:window.document.forms'. "['thresholdform'].elements['".$parameter."_setparmval']". @@ -375,18 +498,152 @@ sub display_config_box() { } $r->print('
@@ -351,7 +474,7 @@ sub display_config_box() {

- + +
'); } +#------------------------------- +# 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('
'.&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]',''. + $$interval_titles{$current}.'.')); + } + $r->print('

+
+ + +   +
'); + 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('
'.&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.').'
'.&mt('This can increase the time taken to gather data for the [_1] page by a few seconds.',"What's New?").'  '.&mt('Currently set to [_1] .'),"$current."); + $r->print('

+
'. +&mt('Display of unread post counts?').'  + + +on +    +off +'); + $r->print('

+
'); + 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"); +
$lt{'chwp'} +
$lt{'cuva'}: +$$initpage{$control} $lt{'anis'} +$$initpage{$current}.

+
+ + +$lt{'padc'}   +END + foreach my $choice (@chgstate) { + $r->print(''.$$initpage{$choice}.'  '); + } + $r->print('

'.&mt('If').' '.$$initpage{'coursespecific'}. + '
'.$lt{'chce'}." \n"); + foreach my $choice (@chgentry) { + $r->print(''.$$initpage{$choice}.'  '); + } + $r->print('

'); + return; +} + +sub curr_courseinit { + my $current = &get_current($env{'user.name'},$env{'user.domain'}, + $env{'request.course.id'},'courseinit'); + my $control; + if ($current) { + $control = 'coursespecific'; + } else { + $control = 'userpref'; + my %userenv = &Apache::lonnet::get('environment', + ['course_init_display']); + if (exists($userenv{'course_init_display'})) { + $current = $userenv{'course_init_display'}; + } + unless ($current) { + $current = 'whatsnew'; + } + } + return ($control,$current); +} + sub display_launcher { - my ($r,$action,$checkallowed,$tabbg,$rowColor1,$rowColor2,$show, + 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) = @_; + $critmsgcount,$critmsgs,$interval,$countunread) = @_; if ($$checkallowed{$action}) { - &start_box($r,$tabbg,$show,$headings,$action); + &start_box($r,$tabbg,$show,$headings,$action,$refpage); if ($$show{$action}) { if ($action eq 'handgrading') { # UNGRADED ITEMS &display_handgrade($r,$tograde,$rowColor1,$rowColor2, @@ -399,11 +656,11 @@ sub display_launcher { $rowColor2,$interval); } elsif ($action eq 'abovethreshold') { # DEGDIFF/AV. TRIES TRIGGERS - &display_abovethreshold($r,$warnings,$triggered,$res_title, - $rowColor1,$rowColor2); + &display_abovethreshold($r,$refpage,$warnings,$triggered, + $res_title,$rowColor1,$rowColor2); } elsif ($action eq 'coursediscussion') { # UNREAD COURSE DISCUSSION &display_coursediscussion($r,$newdiscussions,$unread, - $res_title); + $countunread,$res_title,$rowColor1,$rowColor2); } elsif ($action eq 'coursenormalmail') { # NORMAL MESSAGES &display_coursenormalmail($r,$msgcount,$newmsgs,$rowColor1, $rowColor2); @@ -420,19 +677,21 @@ sub display_launcher { sub getitems { my ($unread,$ungraded,$bombed,$triggered,$changed,$newdiscussions, $tograde,$bombs,$warnings,$rowColor1,$rowColor2,$threshold,$cdom,$crs, - $res_title,$show,$starttime) = @_; + $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 @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{'coursediscussions'}) { + if ($$show{'coursediscussion'}) { my %lastread = &Apache::lonnet::dump('nohist_'. $env{'request.course.id'}.'_discuss', $env{'user.domain'},$env{'user.name'},'lastread'); @@ -461,10 +720,10 @@ sub getitems { $$res_title{$symb} = $title; my $ressymb = $resource->wrap_symb(); -# Check for unread discussion postings +# Check if there are unread discussion postings if ($$show{'coursediscussion'}) { &check_discussions($cdom,$crs,$resource,$symb,$ressymb,$title, - $newdiscussions,$unread,\%lastreadtime); + $newdiscussions,$unread); } # Check for ungraded problems @@ -487,38 +746,73 @@ sub getitems { } } + 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, - $lastreadtime) = @_; -# Check for unread discussion postings + my ($cdom,$crs,$resource,$symb,$ressymb,$title,$newdiscussions, + $unread) = @_; if ($resource->hasDiscussion()) { - my $prevread = 0; - my $unreadcount = 0; %{$$unread{$ressymb}} = (); $$unread{$ressymb}{'title'} = $title; $$unread{$ressymb}{'symb'} = $symb; - if (defined($$lastreadtime{$ressymb})) { - $prevread = $$lastreadtime{$ressymb}; - } - my %contrib = &Apache::lonnet::restore($ressymb, - $env{'request.course.id'},$cdom,$crs); - if ($contrib{'version'}) { - for (my $id=1;$id<=$contrib{'version'};$id++) { - unless (($contrib{'hidden'}=~/\.$id\./) || - ($contrib{'deleted'}=~/\.$id\./)) { - if ($prevread <$contrib{$id.':timestamp'}) { - $$unread{$ressymb}{$unreadcount} = $id.': '.$contrib{$id.':subject'}; + 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'}; } } } } - if ($unreadcount) { push(@{$newdiscussions}, $ressymb); } + $$unread{$ressymb}{'unreadcount'} = $unreadcount; } } + sub check_handgraded { my ($resource,$symb,$title,$cdom,$cnum,$ungraded,$tograde) = @_; if ($resource->is_problem()) { @@ -639,25 +933,57 @@ sub check_thresholds { sub get_curr_thresholds { - my ($threshold,$cdom,$crs) = @_; - my %coursesettings = &Apache::lonnet::dump('environment', - $cdom,$crs,'internal.threshold'); - if (exists($coursesettings{'internal.threshold_av_attempts'})) { - $$threshold{'av_attempts'} = $coursesettings{'internal.threshold_av_attempts'}; + 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 =~ /^(con_lost|error|no_such_host)/i) { + foreach my $item (keys %{$threshold}) { + if (exists($thresholdsettings{$cid.':threshold_'.$item})) { + $$threshold{$item} = + $thresholdsettings{$cid.':threshold_'.$item}; + $thresholdcount ++; + } + } } - if (exists($coursesettings{'internal.threshold_degdiff'})) { - $$threshold{'degdiff'} = $coursesettings{'internal.threshold_degdiff'}; + if ($thresholdcount == 3) { + return; } - if (exists($coursesettings{'internal.threshold_numstudents'})) { - $$threshold{'numstudents'} = $coursesettings{'internal.threshold_numstudents'}; + my %coursesettings = &Apache::lonnet::dump('environment', + $cdom,$crs,'internal.threshold'); + my ($temp) = %coursesettings; + unless ($temp =~ /^(con_lost|error|no_such_host)/i) { + foreach my $item (keys %{$threshold}) { + unless (exists($thresholdsettings{$cid.':threshold_'.$item})) { + if (exists($coursesettings{'internal.threshold_'.$item})) { + $$threshold{$item} = + $coursesettings{'internal.threshold_'.$item}; + } + } + } + } + return; +} + +sub get_current { + my ($uname,$udom,$cid,$caller) = @_; + my $currvalue; + my %settings = &Apache::lonnet::dump('nohist_whatsnew',$udom,$uname,$cid. + ':'.$caller); + my ($tmp) = %settings; + unless ($tmp =~ /^(con_lost|error|no_such_host)/i) { + $currvalue = $settings{$cid.':'.$caller}; } + return $currvalue; } sub process_reset { my ($dom,$crs) = @_; - my $result = 'Counters reset for following problems (and parts):
'; + my $result = ''.&mt('Counters reset for following problems (and parts):'). + '
'; my @agg_types = ('attempts','users','correct'); - my %agg_titles = ( + my %agg_titles = &Apache::lonlocal::texthash ( attempts => 'Number of submissions', users => 'Students with submissions', correct => 'Number of correct submissions', @@ -693,17 +1019,17 @@ sub process_reset { } sub process_update { - my ($dom,$crs,$threshold_titles) = @_; + my ($uname,$udom,$threshold_titles) = @_; my $setoutput = 'Changes to threshold(s) for problem tracking:
'; 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('environment', - {$name=>$value},$dom,$crs); + my $put_result = &Apache::lonnet::put('nohist_whatsnew', + {$name=>$value},$udom,$uname); - my ($shortname) = ($name =~ /^internal\.threshold_(.+)$/); + my ($shortname) = ($name =~ /^\Q$env{'request.course.id'}\E:threshold_(.+)$/); if ($put_result eq 'ok') { $setoutput.=&mt('Set threshold for [_1] to [_2]', ''.$$threshold_titles{$shortname}.'', @@ -788,10 +1114,7 @@ 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 { + unless ($tmp =~ /^(con_lost|error|no_such_host)/i) { if (keys(%changes) > 0) { foreach my $key (sort(keys(%changes))) { if ($changes{$key} > $starttime) { @@ -884,7 +1207,7 @@ sub display_haserrors { } sub display_abovethreshold { - my ($r,$warnings,$triggered,$res_title,$rowColor1,$rowColor2) = @_; + my ($r,$refpage,$warnings,$triggered,$res_title,$rowColor1,$rowColor2) = @_; my %lt = &Apache::lonlocal::texthash( reso => 'Resource', part => 'Part', @@ -900,8 +1223,10 @@ sub display_abovethreshold { my $warningnum = 0; if (@{$warnings} > 0) { @{$warnings} = sort { &cmp_title($a,$b,$res_title) } @{$warnings}; - $r->print('
'. - ' '."\n"); + $r->print(''. + ' '."\n". + ' '. + "\n"); $r->print('
'.$lt{'reso'}.''.$lt{'part'}.''.$lt{'nust'}.''.$lt{'avat'}.''.$lt{'dedi'}.''.$lt{'lare'}.''.$lt{'reco'}.'
'.$lt{'loca'}. ''.$lt{'type'}. - ''.$lt{'numn'}. - '
'.$lt{'tmlp'}.''.$lt{'numn'}. + ''.$lt{'tmlp'}. + '
'.$forum_title.' '.$type.''.$unreadnum.' 
'.$forum_title.' '.$type.' '.$lastpost.''. + '',$unreadnum.' '.$lastpost.'

 '. @@ -1055,12 +1396,10 @@ sub cmp_title { } sub get_display_settings { - my $udom = $env{'user.domain'}; - my $uname = $env{'user.name'}; - my $cid = $env{'request.course.id'}; + my ($uname,$udom,$cid) = @_; my %settings = &Apache::lonnet::dump('nohist_whatsnew',$udom,$uname,$cid); my ($tmp) = keys(%settings); - if ($tmp=~/^error:/) { + if ($tmp=~ /^(con_lost|error|no_such_host)/i) { %settings = (); unless ($tmp eq 'error: 2 tie(GDBM) Failed while attempting dump') { &logthis('Error retrieving whatsnew settings: '.$tmp.' for '. @@ -1070,20 +1409,133 @@ sub get_display_settings { 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]', + ''.$$interval_titles{$env{'form.interval'}}.'
'); + + } 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].', + ''.$$interval_titles{$env{'form.interval'}}.'', + ''.$outcome.'.
'); + } + } + 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]', + ''.$env{'form.countunread'}.'
'); + + } 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].', + ''.$env{'form.countunread'}.'', + ''.$outcome.'.
'); + } + } + 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]',"user's global preferences."); + } else { + $result = &mt('Page displayed after role selection in this course set to [_1]',''.$$initpage{$env{'form.courseinit_page'}}.'.'); + } + } 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].', + ''.$page_control.'', + ''.$outcome.'.
'); + } else { + $result = &mt('Unable to set page display, after role selection, for this course to [_1] due to [_2].', + ''.$$initpage{$env{'form.courseinit_page'}}.'', + ''.$outcome.'.
'); + } + } + } + } + return $result; +} + sub start_box { - my ($r,$tabbg,$show,$heading,$caller) = @_; + 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 = 'Hide'; + $showhide = 'Hide'; } else { - $showhide = 'Show'; + $showhide = 'Show'; } $r->print(' @@ -1102,15 +1554,26 @@ sub start_box {
'.$lt{'chth'}.''.$lt{'chth'}.'
'.$lt{'chin'}.'
'.$lt{'chin'}.''.$lt{'chop'}.'