--- rat/lonpage.pm	2016/10/29 13:47:21	1.111.2.4
+++ rat/lonpage.pm	2017/02/22 22:10:20	1.122
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Page Handler
 #
-# $Id: lonpage.pm,v 1.111.2.4 2016/10/29 13:47:21 raeburn Exp $
+# $Id: lonpage.pm,v 1.122 2017/02/22 22:10:20 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -41,6 +41,7 @@ use Apache::lonxml();
 use Apache::lonlocal;
 use Apache::lonmenu;
 use Apache::lonhomework;
+use Apache::lonparmset;
 use HTML::TokeParser;
 use GDBM_File;
 use Apache::lonsequence;
@@ -184,6 +185,7 @@ sub handler {
       my $fn=$env{'request.course.fn'};
       if (-e "$fn.db") {
           my %buttonshide;
+          my $hostname = $r->hostname();
           if (tie(%hash,'GDBM_File',"$fn.db",&GDBM_READER(),0640)) {
 # ------------------------------------------------------------------- Hash tied
               my $firstres=$hash{'map_start_'.$requrl};
@@ -191,16 +193,24 @@ sub handler {
               if (($firstres) && ($lastres)) {
 # ------------------------------------------------------------- Countdown Timer
                   my $now = time;
-                  my ($pagefirstaccess,%hastimeleft,%countdowndisp);
+                  my ($pagefirstaccess,%hastimeleft,%countdowndisp,%donebutton,
+                      %donebtnextra,%buttonbytime,$donetime,$symbtosetdone);
                   my ($pagesymb,$courseid,$domain,$name)=&Apache::lonnet::whichuser();
+                  unless ($pagesymb) {
+                      $pagesymb=&Apache::lonnet::symbread($requrl);
+                  }
                   if ($pagesymb && ($courseid ne '') && ($domain ne '') && ($name ne '')) {
                       my %times=&Apache::lonnet::get('firstaccesstimes',
                                                      [$courseid."\0".$pagesymb],
                                                      $domain,$name);
                       if ($times{$courseid."\0".$pagesymb} =~ /^\d+$/) {
                           $pagefirstaccess = $times{$courseid."\0".$pagesymb};
+                          if ($pagefirstaccess && $env{'form.LC_interval_done'} eq 'true') {
+                              $donetime = $now - $pagefirstaccess;
+                          }
                       }
                   }
+
 # ----------------------------------------------------------------- Render page
 
                   @rows=();
@@ -218,6 +228,27 @@ sub handler {
 			    my ($mapid,$resid)=split(/\./,$rid);
 			    $symbhash{$hash{'src_'.$rid}}=
 				[$hash{'src_'.$rid},$resid];
+                            if (($donetime) && ($symbtosetdone eq '')) {
+                                my $src = $hash{'src_'.$rid};
+                                if ($hash{'encrypted_'.$rid}) {
+                                    $src=&Apache::lonenc::encrypted($src);
+                                }
+                                my ($mapid,$resid)=split(/\./,$rid);
+                                my $symb=&Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},$resid,$src);
+                                if ($src =~ /$LONCAPA::assess_re/) {
+                                    my @interval=&Apache::lonnet::EXT("resource.0.interval",$symb);
+                                    if (@interval > 1) {
+                                        if (($interval[1] eq 'map') && ($pagefirstaccess)) {
+                                            my ($timelimit) = ($interval[0] =~ /^(\d+)/);
+                                            if ($timelimit) {
+                                                if ($pagefirstaccess + $timelimit > $now) {
+                                                    $symbtosetdone = $symb;
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
 		        }
 		     }
 		  }
@@ -252,6 +283,16 @@ sub handler {
                   my $xmlheader='';
                   my $xmlbody='';
 
+# ---------------------------------------------------------- Handle Done button
+
+                  # Set the event timer to zero if the "done button" was clicked.
+                  if ($donetime && $symbtosetdone) {
+                      &Apache::lonparmset::storeparm_by_symb_inner($symbtosetdone,'0_interval',
+                                                                   2,$donetime,'date_interval',
+                                                                   $name,$domain);
+                      undef($env{'form.LC_interval_done'});
+                  }
+
 # --------------------------------------------- Get SSI output, post parameters
 
                   for ($i=0;$i<=$#rows;$i++) {
@@ -316,9 +357,6 @@ ENDEXT
 				      $posthash{'all_submit'}='yes';
 				  }
 			      }
-                              if ($env{'environment.remote'} eq 'on') {
-                                  $posthash{'inhibitmenu'} = 'yes';
-                              }
                               my $output=Apache::lonnet::ssi($src,%posthash);
 			      $output=~s|//(\s*<!--)? BEGIN LON-CAPA Internal.+?// END LON-CAPA Internal\s*(-->)?\s||gs;
                               if (($target eq 'tex') || ($target eq 'tex_answer')) {
@@ -450,7 +488,8 @@ ENDEXT
                                           undef(%Apache::lonhomework::history);
                                           my $probstatus = &Apache::lonnet::EXT("resource.0.problemstatus",$symb);
                                           if (($status eq 'CAN_ANSWER') || (($status eq 'CANNOT_ANSWER') && 
-                                              (($probstatus eq 'no') || ($probstatus eq 'no_feedback_ever')))) {
+                                              (($probstatus eq 'no') || ($probstatus eq 'no_feedback_ever'))) ||
+                                              (($status eq 'NOT_YET_VIEWED') && ($posthash{'markaccess'} eq 'yes'))) {
                                               my ($slothastime,$timerhastime);
                                               if ($slot_name ne '') {
                                                   if (ref($slot) eq 'HASH') {
@@ -463,11 +502,26 @@ ENDEXT
                                               my $duedate = &Apache::lonnet::EXT("resource.0.duedate",$symb);
                                               my @interval=&Apache::lonnet::EXT("resource.0.interval",$symb);
                                               if (@interval > 1) {
-                                                  my $first_access=&Apache::lonnet::get_first_access($interval[1],$symb);
+                                                  my $first_access;
+                                                  if ($interval[1] eq 'map') {
+                                                      my $ignorecache;
+                                                      if ($env{'form.'.$prefix.'markaccess'} eq 'yes') {
+                                                          $ignorecache = 1;
+                                                      }
+                                                      $first_access=&Apache::lonnet::get_first_access($interval[1],undef,$pagesymb,$ignorecache);
+                                                      if (($first_access) && (!$pagefirstaccess)) {
+                                                          $pagefirstaccess = $first_access;
+                                                      }
+                                                  } else {
+                                                      $first_access=&Apache::lonnet::get_first_access($interval[1],$symb);
+                                                  }
                                                   if ($first_access > 0) {
-                                                      my $timeremains = $first_access+$interval[0] - $now;
-                                                      if ($timeremains > 0) {
-                                                          $timerhastime = $timeremains;
+                                                      my ($timelimit) = ($interval[0] =~ /^(\d+)/);
+                                                      if ($timelimit) {
+                                                          my $timeremains = $timelimit + $first_access - $now;
+                                                          if ($timeremains > 0) {
+                                                              $timerhastime = $timeremains;
+                                                          }
                                                       }
                                                   }
                                               }
@@ -479,6 +533,28 @@ ENDEXT
                                                       $countdowndisp{$symb} = 'inline';
                                                       if ((@interval > 1) && ($timerhastime)) {
                                                           $hastimeleft{$symb} = $timerhastime;
+                                                          if ($pagefirstaccess) {
+                                                              my ($timelimit,$usesdone,$donebuttontext,$proctor,$secret);
+                                                              ($timelimit,my $donesuffix) = split(/_/,$interval[0],2);
+                                                              if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
+                                                                  $usesdone = 'done';
+                                                                  $donebuttontext = $1;
+                                                                  (undef,$proctor,$secret) = split(/_/,$2);
+                                                              } elsif ($donesuffix =~ /^done(|_.+)$/) {
+                                                                  $donebuttontext = &mt('Done');
+                                                                  ($usesdone,$proctor,$secret) = split(/_/,$donesuffix);
+                                                              }
+                                                              if ($usesdone eq 'done') {
+                                                                  $donebutton{$symb} = $timelimit;
+                                                                  push(@{$buttonbytime{$timelimit}},$symb);
+                                                                  $donebtnextra{$symb} = {
+                                                                                              text    => $donebuttontext,
+                                                                                              proctor => $proctor,
+                                                                                              secret  => $secret,
+                                                                                              type    => $interval[1],
+                                                                                         };
+                                                              }
+                                                          }
                                                       } else {
                                                           $hastimeleft{$symb} = $slothastime;
                                                       }
@@ -486,6 +562,9 @@ ENDEXT
                                                       $hastimeleft{$symb} = $duedate - $now;
                                                       $countdowndisp{$symb} = 'none';
                                                   }
+                                                  unless ($donebutton{$symb}) {
+                                                      $donebutton{$symb} = 0;
+                                                  }
                                               }
                                           }
                                       }
@@ -515,7 +594,7 @@ ENDEXT
                       &Apache::loncommon::content_type($r,'text/html');
                       $r->send_http_header;
                       $r->print(&Apache::loncommon::start_page(undef,undef,
-							       {'force_register' => 1}));
+							       {'force_register' => 1,}));
                       $r->print(&mt('This page is either empty or it only contains resources that are currently hidden').'. ');
                       $r->print('<br /><br />'.&mt('Please use the LON-CAPA navigation arrows to move to another item in the course').
 				&Apache::loncommon::end_page());
@@ -565,8 +644,9 @@ ENDEXT
                                       $uniquetimes{$item} = 1;
                                   }
                               }
-                              if (keys(%uniquetimes) == 1) {
-                                  my (%uniquedisplays,%uniquedones,$currdisp);
+                              if (scalar(keys(%uniquetimes)) == 1) {
+                                  my (%uniquedisplays,%uniquedones,$currdisp,$donebuttontime,
+                                      $donebuttonextras);
                                   if (keys(%countdowndisp)) {
                                       foreach my $item (values(%countdowndisp)) {
                                           if (exists($uniquedisplays{$item})) {
@@ -580,7 +660,25 @@ ENDEXT
                                           $currdisp = $countdowndisplay[0];
                                       }
                                   }
-                                  &add_countdown_timer($currdisp);
+                                  if (keys(%donebutton)) {
+                                      foreach my $item (values(%donebutton)) {
+                                          if (exists($uniquedones{$item})) {
+                                              $uniquedones{$item} ++;
+                                          } else {
+                                              $uniquedones{$item} = 1;
+                                          }
+                                      }
+                                      my @donebuttons = sort { $ <=> $b } (keys(%uniquedones));
+                                      if (scalar(@donebuttons) == 1) {
+                                          if ($donebuttons[0]) {
+                                              $donebuttontime = $donebuttons[0];
+                                              if (ref($buttonbytime{$donebuttontime}) eq 'ARRAY') {
+                                                  $donebuttonextras = $donebtnextra{$buttonbytime{$donebuttontime}->[0]};
+                                              }
+                                          }
+                                      }
+                                  }
+                                  &add_countdown_timer($currdisp,$donebuttontime,$donebuttonextras);
                               }
                           }
                           my $pagebuttonshide;
@@ -649,7 +747,7 @@ ENDEXT
                           my $avespan=$lcm/($#colcont+1);
                           for ($j=0;$j<=$#colcont;$j++) {
                               my $rid=$colcont[$j];
-			      my $metainfo =&get_buttons(\%hash,$rid,\%buttonshide).'<br />';
+			      my $metainfo =&get_buttons(\%hash,$rid,\%buttonshide,$hostname).'<br />';
 			    unless (($target eq 'tex') || ($target eq 'tex_answer')) {
 				$r->print('<td colspan="'.$avespan.'"');
 			    }
@@ -777,7 +875,7 @@ ENDEXT
 }
 
 sub get_buttons {
-    my ($hash,$rid,$buttonshide) = @_;
+    my ($hash,$rid,$buttonshide,$hostname) = @_;
 
     my $metainfo = '';
     my $esrc=&Apache::lonnet::declutter($hash->{'src_'.$rid});
@@ -856,7 +954,8 @@ sub get_buttons {
         if ($cfile ne '') {
             my $jscall = &Apache::lonhtmlcommon::jump_to_editres($cfile,$home,$switchserver,
                                                                  $forceedit,1,$symb,undef,
-                                                                 &escape($env{'form.title'}));
+                                                                 &escape($env{'form.title'}),
+                                                                 $hostname);
             if ($jscall) {
                 my $icon = 'pcstr.png';
                 my $label = &mt('Edit');
@@ -871,19 +970,33 @@ sub get_buttons {
 }
 
 sub add_countdown_timer {
-    my ($currdisp) = @_;
-    my ($collapse,$expand,$alttxt,$title);
+    my ($currdisp,$donebuttontime,$donebuttonextras) = @_;
+    my ($collapse,$expand,$alttxt,$title,$donebutton);
     if ($currdisp eq 'inline') {
         $collapse = '&#9658;&nbsp;';
     } else {
         $expand = '&#9668;&nbsp;';
     }
+    if ($donebuttontime) {
+        my ($type,$proctor,$donebuttontext);
+        if (ref($donebuttonextras) eq 'HASH') {
+            $proctor = $donebuttonextras->{'proctor'};
+            $donebuttontext = $donebuttonextras->{'text'};
+            $type = $donebuttonextras->{'type'};
+        } else {
+            $donebuttontext = &mt('Done');
+            $type = 'map';
+        }
+        $donebutton = 
+            &Apache::lonmenu::done_button_js($type,'','',$proctor,$donebuttontext);
+    }
     unless ($env{'environment.icons'} eq 'iconsonly') {
         $alttxt = &mt('Timer');
         $title = $alttxt.'&nbsp;';
     }
     my $desc = &mt('Countdown to due date/time');
     my $output = <<END;
+$donebutton
 <a href="javascript:toggleCountdown();" class="LC_menubuttons_link">
 <span id="ddcountcollapse" class="LC_menubuttons_inline_text">
 $collapse